2 * $Id: queries.c,v 1.22 2009-10-13 22:55:37 didg Exp $
4 * Copyright (c) 1990,1994 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
15 #include <atalk/logger.h>
16 #include <sys/param.h>
18 #include <sys/types.h>
19 #include <netatalk/at.h>
20 #include <atalk/atp.h>
24 #include <kerberos/krb.h>
37 int cq_default( struct papfile *, struct papfile * );
38 int cq_k4login( struct papfile *, struct papfile * );
39 int cq_uameth( struct papfile *, struct papfile * );
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 * );
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 * );
54 int cq_listq( struct papfile *, struct papfile * );
55 int cq_rbilogin( struct papfile *, struct papfile * );
56 #endif /* HAVE_CUPS */
60 int cq_default( struct papfile *in, struct papfile *out)
62 char *start, *stop, *p;
63 int linelength, crlflength;
64 struct papd_comment *comment = compeek();
67 switch ( markline( in, &start, &linelength, &crlflength )) {
78 stop = start+linelength;
80 if ( comgetflags() == 0 ) { /* started */
81 if ( comment->c_end ) {
85 CONSUME( in, linelength + crlflength );
90 if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
91 for ( p = start; p < stop; p++ ) {
103 append( out, p, stop - p + crlflength );
105 CONSUME( in, linelength + crlflength );
110 CONSUME( in, linelength + crlflength );
115 char *LoginOK = "LoginOK\n";
116 char *LoginFailed = "LoginFailed\n";
118 #define h2b(x) (isdigit((x))?(x)-'0':(isupper((x))?(x)-'A':(x)-'a')+10)
120 int cq_k4login( struct papfile *in, struct papfile *out)
123 int linelength, crlflength;
125 struct papd_comment *comment = compeek();
130 switch ( markline( in, &start, &linelength, &crlflength )) {
141 p = start + strlen( comment->c_begin );
142 while ( *p == ' ' ) {
146 bzero( &tkt, sizeof( tkt ));
147 stop = start+linelength;
149 for ( i = 0, t = tkt.dat; p < stop; p += 2, t++, i++ ) {
150 *t = ( h2b( (unsigned char)*p ) << 4 ) +
151 h2b( (unsigned char)*( p + 1 ));
155 if (( rc = krb_rd_req( &tkt, "LaserWriter", printer->p_name,
156 0, &ad, "" )) != RD_AP_OK ) {
157 LOG(log_error, logtype_papd, "cq_k4login: %s", krb_err_txt[ rc ] );
158 append( out, LoginFailed, strlen( LoginFailed ));
160 CONSUME( in, linelength + crlflength );
163 LOG(log_info, logtype_papd, "cq_k4login: %s.%s@%s", ad.pname, ad.pinst,
165 lp_person( ad.pname );
166 lp_host( ad.prealm );
168 append( out, LoginOK, strlen( LoginOK ));
170 CONSUME( in, linelength + crlflength);
174 char *uameth = "UMICHKerberosIV\n*\n";
176 int cq_uameth( struct papfile *in, struct papfile *out)
179 int linelength, crlflength;
180 struct papd_comment *c, *comment = compeek();
183 switch ( markline( in, &start, &linelength, &crlflength )) {
194 if ( comgetflags() == 0 ) { /* start */
195 if (( printer->p_flags & P_KRB ) == 0 ) { /* no kerberos */
196 if ( comswitch( queries, cq_default ) < 0 ) {
197 LOG(log_error, logtype_papd, "cq_uameth: can't find default!" );
204 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) { /* end */
205 append( out, uameth, strlen( uameth ));
211 CONSUME( in, linelength + crlflength );
216 int gq_true( struct papfile *out)
218 if ( printer->p_flags & P_SPOOLED ) {
219 append( out, "true\n", 5 );
226 int gq_pagecost( struct papfile *out)
230 /* check for spooler? XXX */
231 if ( printer->p_pagecost_msg != NULL ) {
232 append( out, printer->p_pagecost_msg,
233 strlen( printer->p_pagecost_msg ));
234 } else if ( printer->p_flags & P_ACCOUNT ) {
237 #endif /* ABS_PRINT */
238 sprintf( cost, "%d", printer->p_pagecost );
239 append( out, cost, strlen( cost ));
243 append( out, "\n", 1 );
248 int gq_balance( struct papfile *out)
252 if ( lp_pagecost() != 0 ) {
255 sprintf( balance, "$%1.2f\n", printer->p_balance );
256 append( out, balance, strlen( balance ));
259 #endif /* ABS_PRINT */
263 * Handler for RBISpoolerID
266 static const char *spoolerid = "(PAPD Spooler) 1.0 (" VERSION ")\n";
268 int gq_rbispoolerid( struct papfile *out)
270 append( out, spoolerid, strlen( spoolerid ));
277 * Handler for RBIUAMListQuery
280 static const char *nouams = "*\n";
282 int gq_rbiuamlist( struct papfile *out)
284 char uamnames[128] = "\0";
286 if (printer->p_flags & P_AUTH_PSSP) {
287 if (getuamnames(UAM_SERVER_PRINTAUTH, uamnames) < 0) {
288 append(out, nouams, strlen(nouams));
291 append(out, uamnames, strlen(uamnames));
295 append(out, nouams, strlen(nouams));
305 { "UMICHCostPerPage", gq_pagecost },
307 { "UMICHUserBalance", gq_balance },
309 { "RBISpoolerID", gq_rbispoolerid },
310 { "RBIUAMListQuery", gq_rbiuamlist },
311 { "ADOIsBinaryOK?", gq_true },
312 { "UMICHListQueue", gq_true },
313 { "UMICHDeleteJob", gq_true },
317 int cq_query( struct papfile *in, struct papfile *out)
319 char *start, *stop, *p, *q;
320 int linelength, crlflength;
321 struct papd_comment *comment = compeek();
326 switch ( markline( in, &start, &linelength, &crlflength )) {
337 stop = start+linelength;
339 if ( comgetflags() == 0 ) { /* started */
342 for ( p = start; p < stop; p++ ) {
348 if (p < stop) for ( p++; p < stop; p++ ) {
349 if ( *p != ' ' && *p != '\t' ) {
354 for ( q = p; q < stop; q++ ) {
355 if ( *q == ' ' || *q == '\t' || *q == '\r' || *q == '\n' ) {
360 for ( gq = genqueries; gq->gq_name; gq++ ) {
361 if (( strlen( gq->gq_name ) == (size_t)(q - p) ) &&
362 ( strncmp( gq->gq_name, p, q - p ) == 0 )) {
366 if ( gq->gq_name == NULL || gq->gq_handler == NULL ||
367 (gq->gq_handler)( out ) < 0 ) {
368 if ( comswitch( queries, cq_default ) < 0 ) {
369 LOG(log_error, logtype_papd, "cq_feature: can't find default!" );
375 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
377 CONSUME( in, linelength + crlflength );
382 CONSUME( in, linelength + crlflength );
386 void cq_font_answer( char *start, char *stop, struct papfile *out)
388 char *p, *q, buf[ 256 ];
389 struct ppd_font *pfo;
393 unsigned int count = 0;
394 while (( *p == ' ' || *p == '\t' ) && p < stop ) {
399 while ( *p != ' ' && *p != '\t' &&
400 *p != '\n' && *p != '\r' && p < stop && count < sizeof(buf)) {
408 append( out, "/", 1 );
409 append( out, buf, strlen( buf ));
410 append( out, ":", 1 );
412 if (( pfo = ppd_font( buf )) == NULL ) {
413 append( out, "No\n", 3 );
415 append( out, "Yes\n", 4 );
423 int cq_font(struct papfile *in, struct papfile *out)
425 char *start, *stop, *p;
426 int linelength, crlflength;
427 struct papd_comment *comment = compeek();
430 switch ( markline( in, &start, &linelength, &crlflength )) {
441 stop = start + linelength;
443 if ( comgetflags() == 0 ) {
446 for ( p = start; p < stop; p++ ) {
454 cq_font_answer( p, stop, out );
456 if ( comgetflags() == 1 &&
457 comcmp( start, stop, comcont, 0 ) == 0 ) {
460 for ( p = start; p < stop; p++ ) {
468 cq_font_answer( p, stop, out );
471 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
472 append( out, "*\n", 2 );
474 CONSUME( in, linelength + crlflength );
480 CONSUME( in, linelength + crlflength );
484 int cq_feature( struct papfile *in, struct papfile *out)
486 char *start, *stop, *p;
487 int linelength, crlflength;
488 struct papd_comment *comment = compeek();
489 struct ppd_feature *pfe;
492 switch ( markline( in, &start, &linelength, &crlflength )) {
503 stop = start + linelength;
505 if ( comgetflags() == 0 ) {
508 /* parse for feature */
509 for ( p = start; p < stop; p++ ) {
516 while ( *p == ' ' ) {
520 if (( pfe = ppd_feature( p, stop - p )) == NULL ) {
521 if ( comswitch( queries, cq_default ) < 0 ) {
522 LOG(log_error, logtype_papd, "cq_feature: can't find default!" );
528 append( out, pfe->pd_value, strlen( pfe->pd_value ));
529 append( out, "\r", 1 );
531 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
533 CONSUME( in, linelength + crlflength );
538 CONSUME( in, linelength + crlflength );
542 static const char *psver = "*PSVersion\n";
543 static const char *prod = "*Product\n";
545 int cq_printer(struct papfile *in, struct papfile *out)
548 int linelength, crlflength;
549 struct papd_comment *comment = compeek();
550 struct ppd_feature *pdpsver, *pdprod;
553 switch ( markline( in, &start, &linelength, &crlflength )) {
564 if ( comgetflags() == 0 ) {
567 if (( pdpsver = ppd_feature( psver, strlen( psver ))) == NULL ) {
568 if ( comswitch( queries, cq_default ) < 0 ) {
569 LOG(log_error, logtype_papd, "cq_printer: can't find default!" );
575 for ( p = pdpsver->pd_value; *p != '\0'; p++ ) {
581 LOG(log_error, logtype_papd, "cq_printer: can't parse PSVersion!" );
582 if ( comswitch( queries, cq_default ) < 0 ) {
583 LOG(log_error, logtype_papd, "cq_printer: can't find default!" );
589 if (( pdprod = ppd_feature( prod, strlen( prod ))) == NULL ) {
590 if ( comswitch( queries, cq_default ) < 0 ) {
591 LOG(log_error, logtype_papd, "cq_printer: can't find default!" );
598 append( out, p + 1, strlen( p + 1 ));
599 append( out, "\r", 1 );
602 append( out, pdpsver->pd_value, p - pdpsver->pd_value );
603 append( out, "\r", 1 );
606 append( out, pdprod->pd_value, strlen( pdprod->pd_value ));
607 append( out, "\r", 1 );
609 if ( comcmp( start, start+linelength, comment->c_end, 0 ) == 0 ) {
611 CONSUME( in, linelength + crlflength );
616 CONSUME( in, linelength + crlflength );
622 static const char *rmjobfailed = "Failed\n";
623 static const char *rmjobok = "Ok\n";
625 int cq_rmjob( struct papfile *in, struct papfile *out)
627 char *start, *stop, *p;
628 int linelength, crlflength;
631 switch ( markline( in, &start, &linelength, &crlflength )) {
642 stop = start + linelength;
644 for ( p = start; p < stop; p++ ) {
645 if ( *p == ' ' || *p == '\t' ) {
649 for ( ; p < stop; p++ ) {
650 if ( *p != ' ' && *p != '\t' ) {
656 if ( p < stop && ( job = atoi( p )) > 0 ) {
658 append( out, rmjobok, strlen( rmjobok ));
660 append( out, rmjobfailed, strlen( rmjobfailed ));
664 CONSUME( in, linelength + crlflength );
668 int cq_listq( struct papfile *in, struct papfile *out)
671 int linelength, crlflength;
673 switch ( markline( in, &start, &linelength, &crlflength )) {
684 if ( lp_queue( out )) {
685 LOG(log_error, logtype_papd, "cq_listq: lp_queue failed" );
689 CONSUME( in, linelength + crlflength );
692 #endif /* HAVE_CUPS */
696 * Handler for RBILogin
699 static struct uam_obj *papd_uam = NULL;
700 static const char *rbiloginok = "0\r";
701 static const char *rbiloginbad = "-1\r";
702 static const char *rbiloginerrstr = "%%[Error: SecurityError; \
703 SecurityViolation: Unknown user, incorrect password or log on is \
704 disabled ]%%\r%%[Flushing: rest of job (to end-of-file) will be \
707 int cq_rbilogin( struct papfile *in, struct papfile *out)
709 char *start, *stop, *p, *begin;
710 int linelength, crlflength;
711 char username[UAM_USERNAMELEN + 1] = "\0";
712 struct papd_comment *comment = compeek();
716 switch ( markline( in, &start, &linelength, &crlflength )) {
727 stop = start + linelength;
729 if ( comgetflags() == 0 ) { /* first line */
730 begin = start + strlen(comment->c_begin);
733 while (*p != ' ' && p < stop) {
737 memset(uamtype, 0, sizeof(uamtype));
738 if ((size_t)(p -begin) <= sizeof(uamtype) -1) {
739 strncpy(uamtype, begin, p - begin);
742 if ( !*uamtype || (papd_uam = auth_uamfind(UAM_SERVER_PRINTAUTH,
743 uamtype, strlen(uamtype))) == NULL) {
744 LOG(log_info, logtype_papd, "Could not find uam: %s", uamtype);
745 append(out, rbiloginbad, strlen(rbiloginbad));
746 append(out, rbiloginerrstr, strlen(rbiloginerrstr));
748 if ( (papd_uam->u.uam_printer(p,stop,username,out)) == 0 ) {
749 lp_person( username );
750 append(out, rbiloginok, strlen( rbiloginok ));
751 LOG(log_info, logtype_papd, "RBILogin: Logged in '%s'", username);
753 append(out, rbiloginbad, strlen( rbiloginbad));
754 append(out, rbiloginerrstr, strlen(rbiloginerrstr));
759 if ( comcmp( start, stop, comment->c_end, 0 ) == 0 ) {
765 CONSUME( in, linelength + crlflength );
771 * All queries start with %%?Begin and end with %%?End. Note that the
772 * "Begin"/"End" general queries have to be last.
774 struct papd_comment queries[] = {
776 { "%%Login: UMICHKerberosIV", NULL, cq_k4login, 0 },
777 { "%%?BeginUAMethodsQuery", "%%?EndUAMethodsQuery:", cq_uameth,C_FULL },
780 { "%UMICHListQueue", NULL, cq_listq, C_FULL },
781 { "%UMICHDeleteJob", NULL, cq_rmjob, 0 },
782 #endif /* HAVE_CUPS */
783 { "%%?BeginQuery: RBILogin ", "%%?EndQuery", cq_rbilogin, 0 },
784 { "%%?BeginQuery", "%%?EndQuery", cq_query, 0 },
785 { "%%?BeginFeatureQuery", "%%?EndFeatureQuery", cq_feature, 0 },
786 { "%%?BeginFontQuery", "%%?EndFontQuery", cq_font, 0 },
787 { "%%?BeginPrinterQuery", "%%?EndPrinterQuery", cq_printer,C_FULL },
788 { "%%?Begin", "%%?End", cq_default, 0 },
789 { NULL, NULL, NULL, 0 },