]> arthur.barton.de Git - netatalk.git/blob - etc/papd/main.c
Set version to 2.1
[netatalk.git] / etc / papd / main.c
1 /*
2  * $Id: main.c,v 1.31 2009-10-29 13:38:15 didg Exp $
3  *
4  * Copyright (c) 1990,1995 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
14 #include <sys/param.h>
15 #include <sys/time.h>
16 #include <sys/uio.h>
17 #include <sys/file.h>
18 #include <sys/socket.h>
19 #include <atalk/logger.h>
20
21 /* POSIX.1 sys/wait.h check */
22 #include <sys/types.h>
23 #ifdef HAVE_SYS_WAIT_H
24 #include <sys/wait.h>
25 #endif /* HAVE_SYS_WAIT_H */
26 #ifndef WEXITSTATUS
27 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
28 #endif /* ! WEXITSTATUS */
29 #ifndef WIFEXITED
30 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
31 #endif /* ! WIFEXITED */
32
33 #include <errno.h>
34
35 /* STDC check */
36 #if STDC_HEADERS
37 #include <string.h>
38 #else /* STDC_HEADERS */
39 #ifndef HAVE_STRCHR
40 #define strchr index
41 #define strrchr index
42 #endif /* HAVE_STRCHR */
43 char *strchr (), *strrchr ();
44 #ifndef HAVE_MEMCPY
45 #define memcpy(d,s,n) bcopy ((s), (d), (n))
46 #define memmove(d,s,n) bcopy ((s), (d), (n))
47 #endif /* ! HAVE_MEMCPY */
48 #endif /* STDC_HEADERS */
49
50 #include <signal.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <netdb.h>
54 #include <fcntl.h>
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif /* HAVE_UNISTD_H */
58
59 #include <netatalk/endian.h>
60 #include <netatalk/at.h>
61 #include <atalk/compat.h>
62 #include <atalk/atp.h>
63 #include <atalk/pap.h>
64 #include <atalk/paths.h>
65 #include <atalk/util.h>
66 #include <atalk/nbp.h>
67 #include <atalk/unicode.h>
68
69 #include "printer.h"
70 #include "printcap.h"
71 #include "session.h"
72 #include "uam_auth.h"
73 #include "print_cups.h"
74
75
76 #define PIPED_STATUS    "status: print spooler processing job"
77
78 struct printer  defprinter;
79 struct printer  *printers = NULL;
80
81 int             debug = 0;
82 static char     *conffile = _PATH_PAPDCONF;
83 char            *printcap = _PATH_PAPDPRINTCAP;
84 unsigned char   connid, quantum, sock, oquantum = PAP_MAXQUANTUM;
85 char            *cannedstatus = PIPED_STATUS;
86 struct printer  *printer = NULL;
87 char            *version = VERSION;
88 static char     *pidfile = _PATH_PAPDLOCK;
89
90 char            *uamlist;
91 char            *uampath = _PATH_PAPDUAMPATH;
92
93 /* Prototypes for locally used functions */
94 int getstatus( struct printer *pr, char *buf );
95 int rprintcap( struct printer *pr );
96 static void getprinters( char *cf );
97
98
99 /* this only needs to be used by the server process */
100 static void papd_exit(const int i)
101 {
102   server_unlock(pidfile);
103   auth_unload();
104   exit(i);
105 }
106
107 static void
108 die(int n)
109 {
110     struct printer      *pr;
111     struct at_addr      addr;
112
113     memset(&addr, 0, sizeof(addr));
114
115     for ( pr = printers; pr; pr = pr->p_next ) {
116         if ( pr->p_flags & P_REGISTERED ) {
117             if ( nbp_unrgstr( pr->p_name, pr->p_type, pr->p_zone, &addr ) < 0 ) {
118                 LOG(log_error, logtype_papd, "can't unregister %s:%s@%s", pr->p_name,
119                         pr->p_type, pr->p_zone );
120                 papd_exit( n + 1 );
121             }
122             LOG(log_info, logtype_papd, "unregister %s:%s@%s", pr->p_name, pr->p_type,
123                     pr->p_zone );
124         }
125 #ifdef HAVE_CUPS
126         if ( pr->p_flags & P_SPOOLED && pr->p_flags & P_CUPS_PPD ) {
127                 LOG(log_info, logtype_papd, "Deleting CUPS temp PPD file for %s (%s)", pr->p_name, pr->p_ppdfile);
128                 unlink (pr->p_ppdfile);
129         }
130 #endif /* HAVE_CUPS */
131
132     }
133     papd_exit( n );
134 }
135
136 static void
137 reap(int sig _U_)
138 {
139     int         status;
140     int         pid;
141
142     while (( pid = wait3( &status, WNOHANG, NULL )) > 0 ) {
143         if ( WIFEXITED( status )) {
144             if ( WEXITSTATUS( status )) {
145                 LOG(log_error, logtype_papd, "child %d exited with %d", pid,
146                         WEXITSTATUS( status ));
147             } else {
148                 LOG(log_info, logtype_papd, "child %d done", pid );
149             }
150         } else {
151             if ( WIFSIGNALED( status )) {
152                 LOG(log_error, logtype_papd, "child %d killed with %d", pid,
153                         WTERMSIG( status ));
154             } else {
155                 LOG(log_error, logtype_papd, "child %d died", pid );
156             }
157         }
158     }
159     return;
160 }
161
162 static char rbuf[ 255 + 1 + 8 ];
163
164 int main(int ac, char **av)
165 {
166     extern char         *optarg;
167
168     ATP                 atp;
169     struct atp_block    atpb;
170     struct sockaddr_at  sat;
171     struct sigaction    sv;
172     struct iovec        iov;
173     fd_set              fdset;
174     struct printer      *pr;
175     char                *p, hostname[ MAXHOSTNAMELEN ];
176     char                cbuf[ 8 ];
177     int                 c;
178     char                *atname;
179
180     if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
181         perror( "gethostname" );
182         exit( 1 );
183     }
184     if (( p = strchr( hostname, '.' )) != NULL ) {
185         *p = '\0';
186     }
187     if (( defprinter.p_name = (char *)malloc( strlen( hostname ) + 1 ))
188             == NULL ) {
189         perror( "malloc" );
190         exit( 1 );
191     }
192     strcpy( defprinter.p_name, hostname );
193     defprinter.p_type = "LaserWriter";
194     defprinter.p_zone = "*";
195     memset(&defprinter.p_addr, 0, sizeof(defprinter.p_addr));
196 #ifdef __svr4__
197     defprinter.p_flags = P_PIPED;
198     defprinter.p_printer = "/usr/bin/lp -T PS";
199 #else /* __svr4__ */
200     defprinter.p_flags = P_SPOOLED;
201     defprinter.p_printer = "lp";
202 #endif /* __svr4__ */
203     defprinter.p_operator = "operator";
204     defprinter.p_spool = _PATH_PAPDSPOOLDIR;
205 #ifdef ABS_PRINT
206     defprinter.p_role = NULL;
207     defprinter.p_srvid = 0;
208 #endif /* ABS_PRINT */
209     defprinter.p_pagecost = 200;                /* default cost */
210     defprinter.p_pagecost_msg = NULL;
211     defprinter.p_lock = "lock";
212
213     while (( c = getopt( ac, av, "adf:p:P:v" )) != EOF ) {
214         switch ( c ) {
215         case 'a' :              /* for compatibility with old papd */
216             break;
217
218         case 'd' :              /* debug */
219             debug++;
220             break;
221
222         case 'f' :              /* conffile */
223             conffile = optarg;
224             break;
225
226         case 'p' :              /* printcap */
227             printcap = optarg;
228             break;
229
230         case 'P' :
231             pidfile = optarg;
232             break;
233
234         case 'v' :              /* version */
235             printf( "papd (version %s)\n", VERSION );
236             exit ( 1 );
237             break;
238
239         default :
240             fprintf( stderr,
241                     "Usage:\t%s [ -d ] [ -f conffile ] [ -p printcap ]\n",
242                     *av );
243             exit( 1 );
244         }
245     }
246
247
248     switch (server_lock("papd", pidfile, debug)) {
249     case 0: /* open a couple things again in the child */
250       if (!debug && (c = open("/", O_RDONLY)) >= 0) {
251         dup2(c, 1);
252         dup2(c, 2);
253       }
254       break;
255     case -1:
256       exit(1);
257     default:
258       exit(0);
259     }      
260
261 #ifdef DEBUG1
262     fault_setup(NULL);
263 #endif
264
265     /*
266      * Start logging.
267      */
268     if (( p = strrchr( av[ 0 ], '/' )) == NULL ) {
269         p = av[ 0 ];
270     } else {
271         p++;
272     }
273 #ifdef ultrix
274     openlog( p, LOG_PID );
275 #else /* ultrix */
276     set_processname(p);
277     syslog_setup(log_debug, logtype_default, logoption_ndelay | logoption_pid |
278                debug ? logoption_perror : 0, logfacility_lpr );
279 #endif /* ultrix */
280
281     LOG(log_info, logtype_papd, "restart (%s)", version );
282 #ifdef HAVE_CUPS
283     LOG(log_info, logtype_papd, "CUPS support enabled (%s)", CUPS_API_VERSION );
284 #endif
285
286     getprinters( conffile );
287
288     for ( pr = printers; pr; pr = pr->p_next ) {
289         if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) < 0 ) {
290             LOG(log_error, logtype_papd, "printcap problem: %s", pr->p_printer );
291         }
292
293         if (!(pr->p_flags & P_CUPS)) {
294                 if ((size_t)-1 != convert_string_allocate(CH_UNIX, CH_MAC, pr->p_name, -1, &atname)) {
295                         pr->p_u_name = pr->p_name;
296                         pr->p_name = atname;
297                 }
298         }
299                         
300         if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) {
301             LOG(log_error, logtype_papd, "atp_open: %s", strerror(errno) );
302             papd_exit( 1 );
303         }
304         if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type,
305                 pr->p_zone ) < 0 ) {
306             LOG(log_error, logtype_papd, "can't register %s:%s@%s", pr->p_u_name, pr->p_type,
307                     pr->p_zone );
308             die( 1 );
309         }
310         if ( pr->p_flags & P_AUTH ) {
311                 LOG(log_info, logtype_papd, "Authentication enabled: %s", pr->p_u_name );
312         }
313         else {
314                 LOG(log_info, logtype_papd, "Authentication disabled: %s", pr->p_u_name );
315         }
316         LOG(log_info, logtype_papd, "register %s:%s@%s", pr->p_u_name, pr->p_type,
317                 pr->p_zone );
318         pr->p_flags |= P_REGISTERED;
319     }
320
321     memset(&sv, 0, sizeof(sv));
322     sv.sa_handler = die;
323     sigemptyset( &sv.sa_mask );
324     sv.sa_flags = SA_RESTART;
325     if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) {
326         LOG(log_error, logtype_papd, "sigaction: %s", strerror(errno) );
327         papd_exit( 1 );
328     }
329
330     sv.sa_handler = reap;
331     sigemptyset( &sv.sa_mask );
332     sv.sa_flags = SA_RESTART;
333     if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) {
334         LOG(log_error, logtype_papd, "sigaction: %s", strerror(errno) );
335         papd_exit( 1 );
336     }
337
338     /*
339      * Load UAMS
340      */
341     auth_load(uampath, uamlist);
342
343     /*
344      * Begin accepting connections.
345      */
346     FD_ZERO( &fdset );
347     for (;;) {
348         for ( pr = printers; pr; pr = pr->p_next ) {
349             FD_SET( atp_fileno( pr->p_atp ), &fdset );
350         }
351         if (( c = select( FD_SETSIZE, &fdset, NULL, NULL, NULL )) < 0 ) {
352             if ( errno == EINTR ) {
353                 continue;
354             }
355             LOG(log_error, logtype_papd, "select: %s", strerror(errno) );
356             papd_exit( 1 );
357         }
358
359         for ( pr = printers; pr; pr = pr->p_next ) {
360             if ( FD_ISSET( atp_fileno( pr->p_atp ), &fdset )) {
361                 int             err = 0;
362
363                 memset( &sat, 0, sizeof( struct sockaddr_at ));
364 #ifdef BSD4_4
365                 sat.sat_len = sizeof( struct sockaddr_at );
366 #endif /* BSD4_4 */
367                 sat.sat_family = AF_APPLETALK;
368                 sat.sat_addr.s_net = ATADDR_ANYNET;
369                 sat.sat_addr.s_node = ATADDR_ANYNODE;
370                 sat.sat_port = ATADDR_ANYPORT;
371                 /* do an atp_rsel(), to prevent hangs */
372                 if (( c = atp_rsel( pr->p_atp, &sat, ATP_TREQ )) != ATP_TREQ ) {
373                     continue;
374                 }
375                 atpb.atp_saddr = &sat;
376                 atpb.atp_rreqdata = cbuf;
377                 atpb.atp_rreqdlen = sizeof( cbuf );
378                 if ( atp_rreq( pr->p_atp, &atpb ) < 0 ) {
379                     LOG(log_error, logtype_papd, "atp_rreq: %s", strerror(errno) );
380                     continue;
381                 }
382
383                 /* should check length of req buf */
384
385                 switch( cbuf[ 1 ] ) {
386                 case PAP_OPEN :
387                     connid = (unsigned char)cbuf[ 0 ];
388                     sock = (unsigned char)cbuf[ 4 ];
389                     quantum = (unsigned char)cbuf[ 5 ];
390                     rbuf[ 0 ] = cbuf[ 0 ];
391                     rbuf[ 1 ] = PAP_OPENREPLY;
392                     rbuf[ 2 ] = rbuf[ 3 ] = 0;
393
394                     if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) != 0 ) {
395                         LOG(log_error, logtype_papd, "printcap problem: %s",
396                                 pr->p_printer );
397                         rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
398                         err = 1;
399                     }
400
401 #ifdef HAVE_CUPS
402                    /*
403                     * If cups is not accepting jobs, we return
404                     * 0xffff to indicate we're busy
405                     */
406 #ifdef DEBUG
407                     LOG(log_debug9, logtype_papd, "CUPS: PAP_OPEN");
408 #endif
409                     if ( (pr->p_flags & P_SPOOLED) && (cups_get_printer_status ( pr ) == 0)) {
410                         LOG(log_error, logtype_papd, "CUPS_PAP_OPEN: %s is not accepting jobs",
411                                 pr->p_printer );
412                         rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
413                         err = 1;
414                     }
415 #endif /* HAVE_CUPS */
416
417                     /*
418                      * If this fails, we've run out of sockets. Rather than
419                      * just die(), let's try to continue. Maybe some sockets
420                      * will close, and we can continue;
421                      */
422                     if (( atp = atp_open( ATADDR_ANYPORT, 
423                                           &pr->p_addr)) == NULL ) {
424                         LOG(log_error, logtype_papd, "atp_open: %s", strerror(errno) );
425                         rbuf[ 2 ] = rbuf[ 3 ] = 0xff;  /* printer busy */
426                         rbuf[ 4 ] = 0; /* FIXME is it right? */
427                         err = 1;
428                     }
429                     else {
430                        rbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
431                     }
432                     rbuf[ 5 ] = oquantum;
433                     rbuf[ 6 ] = rbuf[ 7 ] = 0;
434
435                     iov.iov_base = rbuf;
436                     iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
437                     atpb.atp_sresiov = &iov;
438                     atpb.atp_sresiovcnt = 1;
439                     /*
440                      * This may error out if we lose a route, so we won't die().
441                      */
442                     if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
443                         LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );
444                         err = 1;
445                     }
446
447                     if ( err ) {
448                         if (atp) {
449                            atp_close(atp);
450                         }
451                         continue;
452                     }
453
454                     switch ( c = fork()) {
455                     case -1 :
456                         LOG(log_error, logtype_papd, "fork: %s", strerror(errno) );
457                         atp_close(atp);
458                         continue;
459
460                     case 0 : /* child */
461                         printer = pr;
462
463                         #ifndef HAVE_CUPS
464                         if (( printer->p_flags & P_SPOOLED ) &&
465                                 chdir( printer->p_spool ) < 0 ) {
466                             LOG(log_error, logtype_papd, "chdir %s: %s", printer->p_spool, strerror(errno) );
467                             exit( 1 );
468                         }
469                         #else
470                         if (( printer->p_flags & P_SPOOLED ) &&
471                                 chdir( SPOOLDIR ) < 0 ) {
472                             LOG(log_error, logtype_papd, "chdir %s: %s", SPOOLDIR, strerror(errno) );
473                             exit( 1 );
474                         }
475
476                         #endif
477
478                         sv.sa_handler = SIG_DFL;
479                         sigemptyset( &sv.sa_mask );
480                         sv.sa_flags = SA_RESTART;
481                         if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) {
482                             LOG(log_error, logtype_papd, "sigaction: %s", strerror(errno) );
483                             exit( 1 );
484                         }
485                         
486                         if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) {
487                             LOG(log_error, logtype_papd, "sigaction: %s", strerror(errno) );
488                             exit( 1 );
489                         }
490
491                         for ( pr = printers; pr; pr = pr->p_next ) {
492                             atp_close( pr->p_atp );
493                         }
494                         sat.sat_port = sock;
495                         if ( session( atp, &sat ) < 0 ) {
496                             LOG(log_error, logtype_papd, "bad session" );
497                             exit( 1 );
498                         }
499                         exit( 0 );
500                         break;
501
502                     default : /* parent */
503                         LOG(log_info, logtype_papd, "child %d for \"%s\" from %u.%u",
504                                 c, pr->p_name, ntohs( sat.sat_addr.s_net ),
505                                 sat.sat_addr.s_node);
506                         atp_close( atp );
507                     }
508                     break;
509
510                 case PAP_SENDSTATUS :
511                     rbuf[ 0 ] = 0;
512                     rbuf[ 1 ] = PAP_STATUS;
513                     rbuf[ 2 ] = rbuf[ 3 ] = 0;
514                     rbuf[ 4 ] = rbuf[ 5 ] = 0;
515                     rbuf[ 6 ] = rbuf[ 7 ] = 0;
516
517                     iov.iov_base = rbuf;
518                     iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
519                     atpb.atp_sresiov = &iov;
520                     atpb.atp_sresiovcnt = 1;
521                     /*
522                      * This may error out if we lose a route, so we won't die().
523                      */
524                     if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
525                         LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );
526                     }
527                     break;
528
529                 default :
530                     LOG(log_error, logtype_papd, "Bad request from %u.%u!",
531                             ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node );
532                     continue;
533                     break;
534                 }
535
536 #ifdef notdef
537                 /*
538                  * Sometimes the child process will send its first READ
539                  * before the parent has sent the OPEN REPLY.  Moving this
540                  * code into the OPEN/STATUS switch fixes this problem.
541                  */
542                 iov.iov_base = rbuf;
543                 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
544                 atpb.atp_sresiov = &iov;
545                 atpb.atp_sresiovcnt = 1;
546                 /*
547                  * This may error out if we lose a route, so we won't die().
548                  */
549                 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
550                     LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );
551                 }
552 #endif /* notdef */
553             }
554         }
555     }
556     return 0;
557 }
558
559 /*
560  * We assume buf is big enough for 255 bytes of data and a length byte.
561  */
562
563 int getstatus(struct printer *pr, char *buf)
564 {
565
566 #ifdef HAVE_CUPS
567     if ( pr->p_flags & P_PIPED ) {
568         *buf = strlen( cannedstatus );
569         strncpy( &buf[ 1 ], cannedstatus, *buf );
570         return( *buf + 1 );
571     } else {
572         cups_get_printer_status( pr );
573         *buf = strlen ( pr->p_status );
574         strncpy ( &buf[1], pr->p_status, *buf);
575         return ( *buf + 1);
576     }
577 #else
578
579     char                path[ MAXPATHLEN ];
580     int                 fd = -1, rc;
581
582     if ( pr->p_flags & P_SPOOLED && ( pr->p_spool != NULL )) {
583         strcpy( path, pr->p_spool );
584         strcat( path, "/status" );
585         fd = open( path, O_RDONLY);
586     }
587
588     if (( pr->p_flags & P_PIPED ) || ( fd < 0 )) {
589         *buf = strlen( cannedstatus );
590         strncpy( &buf[ 1 ], cannedstatus, *buf );
591         return( *buf + 1 );
592     } else {
593         if (( rc = read( fd, &buf[ 1 ], 255 )) < 0 ) {
594             rc = 0;
595         }
596         close( fd );
597         if ( rc && buf[ rc ] == '\n' ) {        /* remove trailing newline */
598             rc--;
599         }
600         *buf = rc;
601         return( rc + 1 );
602     }
603 #endif /* HAVE_CUPS */
604 }
605
606 char    *pgetstr(char *id, char **area);
607 char    *getpname(char **area, int bufsize);
608
609 #define PF_CONFBUFFER   1024
610
611 static void getprinters( char *cf)
612 {
613     char                buf[ PF_CONFBUFFER ], area[ PF_CONFBUFFER ], *a, *p, *name, *type, *zone;
614     struct printer      *pr;
615     int                 c;
616
617     while (( c = getprent( cf, buf, PF_CONFBUFFER )) > 0 ) {
618         a = area;
619         /*
620          * Get the printer's nbp name.
621          */
622         if (( p = getpname( &a, PF_CONFBUFFER )) == NULL ) {
623             fprintf( stderr, "No printer name\n" );
624             exit( 1 );
625         }
626
627         if (( pr = (struct printer *)malloc( sizeof( struct printer )))
628                 == NULL ) {
629             perror( "malloc" );
630             exit( 1 );
631         }
632         memset( pr, 0, sizeof( struct printer ));
633
634         name = defprinter.p_name;
635         type = defprinter.p_type;
636         zone = defprinter.p_zone;
637         if ( nbp_name( p, &name, &type, &zone )) {
638             fprintf( stderr, "Can't parse \"%s\"\n", name );
639             exit( 1 );
640         }
641         if ( name != defprinter.p_name ) {
642             if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) {
643                 perror( "malloc" );
644                 exit( 1 );
645             }
646             strcpy( pr->p_name, name );
647         } else {
648             pr->p_name = name;
649         }
650         if ( type != defprinter.p_type ) {
651             if (( pr->p_type = (char *)malloc( strlen( type ) + 1 )) == NULL ) {
652                 perror( "malloc" );
653                 exit( 1 );
654             }
655             strcpy( pr->p_type, type );
656         } else {
657             pr->p_type = type;
658         }
659         if ( zone != defprinter.p_zone ) {
660             if (( pr->p_zone = (char *)malloc( strlen( zone ) + 1 )) == NULL ) {
661                 perror( "malloc" );
662                 exit( 1 );
663             }
664             strcpy( pr->p_zone, zone );
665         } else {
666             pr->p_zone = zone;
667         }
668
669         if ( pnchktc( cf ) != 1 ) {
670             fprintf( stderr, "Bad papcap entry\n" );
671             exit( 1 );
672         }
673
674         /*
675          * Get PPD file.
676          */
677         if (( p = pgetstr( "pd", &a ) )) {
678             if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
679                 perror( "malloc" );
680                 exit( 1 );
681             }
682             strcpy( pr->p_ppdfile, p );
683         }
684
685         /*
686          * Get lpd printer name.
687          */
688         if (( p = pgetstr( "pr", &a )) == NULL ) {
689             pr->p_printer = defprinter.p_printer;
690             pr->p_flags = defprinter.p_flags;
691         } else {
692             if ( *p == '|' ) {
693                 p++;
694                 pr->p_flags = P_PIPED;
695             } else {
696                 pr->p_flags = P_SPOOLED;
697             }
698             if (( pr->p_printer = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
699                 perror( "malloc" );
700                 exit( 1 );
701             }
702             strcpy( pr->p_printer, p );
703         }
704
705         /*
706          * Do we want authenticated printing?
707          */
708         if ((p = pgetstr( "ca", &a )) != NULL ) {
709             if ((pr->p_authprintdir = (char *)malloc(strlen(p)+1)) == NULL) {
710                 perror( "malloc" );
711                 exit(1);
712             }
713             strcpy( pr->p_authprintdir, p );
714             pr->p_flags |= P_AUTH;
715             pr->p_flags |= P_AUTH_CAP;
716         } else { pr->p_authprintdir = NULL; }
717
718         if ( pgetflag( "sp" ) == 1 ) {
719             pr->p_flags |= P_AUTH;
720             pr->p_flags |= P_AUTH_PSSP;
721         }
722
723         if ((p = pgetstr("am", &a)) != NULL ) {
724                 if ((uamlist = (char *)malloc(strlen(p)+1)) == NULL ) {
725                         perror("malloc");
726                         exit(1);
727                 }
728                 strcpy(uamlist, p);
729         }
730
731         if ( pr->p_flags & P_SPOOLED ) {
732             /*
733              * Get operator name.
734              */
735             if (( p = pgetstr( "op", &a )) == NULL ) {
736                 pr->p_operator = defprinter.p_operator;
737             } else {
738                 if (( pr->p_operator = (char *)malloc( strlen( p ) + 1 ))
739                         == NULL ) {
740                     perror( "malloc" );
741                     exit( 1 );
742                 }
743                 strcpy( pr->p_operator, p );
744             }
745         }
746
747         /* get printer's appletalk address. */
748         if (( p = pgetstr( "pa", &a )) == NULL ) 
749             memcpy(&pr->p_addr, &defprinter.p_addr, sizeof(pr->p_addr));
750         else 
751             atalk_aton(p, &pr->p_addr);
752
753 #ifdef HAVE_CUPS
754         if ((p = pgetstr("co", &a)) != NULL ) {
755             pr->p_cupsoptions = strdup(p);
756             LOG (log_error, logtype_papd, "enabling cups-options for %s: %s", pr->p_name, pr->p_cupsoptions);
757         }
758 #endif
759
760         /* convert line endings for setup sections.
761            real ugly work around for foomatic deficiencies,
762            need to get rid of this */
763         if ( pgetflag("fo") == 1 ) {
764             pr->p_flags |= P_FOOMATIC_HACK;
765             LOG (log_error, logtype_papd, "enabling foomatic hack for %s", pr->p_name);
766         }
767
768         if (strncasecmp (pr->p_name, "cupsautoadd", 11) == 0)
769         {
770 #ifdef HAVE_CUPS
771                 pr = cups_autoadd_printers (pr, printers);
772                 printers = pr;
773 #else
774                 LOG (log_error, logtype_papd, "cupsautoadd: Cups support not compiled in");
775 #endif /* HAVE_CUPS */
776         }
777         else {
778 #ifdef HAVE_CUPS
779                 if ( cups_check_printer ( pr, printers, 1) == 0)
780                 {
781                         pr->p_next = printers;
782                         printers = pr;
783                 }
784 #else
785                 pr->p_next = printers;
786                 printers = pr;
787 #endif /* HAVE_CUPS */
788         }
789     }
790     if ( c == 0 ) {
791         endprent();
792     } else {                    /* No capability file, do default */
793         printers = &defprinter;
794     }
795 }
796
797 int rprintcap( struct printer *pr)
798 {
799
800 #ifdef HAVE_CUPS
801
802     char                *p;
803
804     if ( pr->p_flags & P_SPOOLED && !(pr->p_flags & P_CUPS_AUTOADDED) ) { /* Skip check if autoadded */
805         if ( cups_printername_ok ( pr->p_printer ) != 1) {
806             LOG(log_error, logtype_papd, "No such CUPS printer: '%s'", pr->p_printer );
807             return( -1 );
808         }
809     }
810
811     /*
812      * Check for ppd file, moved here because of cups_autoadd we cannot check at the usual location
813      */
814
815     if ( pr->p_ppdfile == NULL ) {
816         if ( (p = (char *) cups_get_printer_ppd ( pr->p_printer )) != NULL ) {
817             if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
818                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
819                 exit( 1 );
820             }
821             strcpy( pr->p_ppdfile, p );
822             pr->p_flags |= P_CUPS_PPD;
823             LOG(log_info, logtype_papd, "PPD File for %s set to %s", pr->p_printer, pr->p_ppdfile );
824         }
825     }
826
827
828 #else
829
830     char                buf[ 1024 ], area[ 1024 ], *a, *p;
831     int                 c;
832
833     /*
834      * Spool directory from printcap file.
835      */
836     if ( pr->p_flags & P_SPOOLED ) {
837         if ( pgetent( printcap, buf, pr->p_printer ) != 1 ) {
838             LOG(log_error, logtype_papd, "No such printer: %s", pr->p_printer );
839             return( -1 );
840         }
841
842         /*
843          * Spool directory.
844          */
845         if ( pr->p_spool != NULL && pr->p_spool != defprinter.p_spool ) {
846             free( pr->p_spool );
847         }
848         a = area;
849         if (( p = pgetstr( "sd", &a )) == NULL ) {
850             pr->p_spool = defprinter.p_spool;
851         } else {
852             if (( pr->p_spool = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
853                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
854                 exit( 1 );
855             }
856             strcpy( pr->p_spool, p );
857         }
858
859         /*
860          * Is accounting on?
861          */
862         a = area;
863         if ( pgetstr( "af", &a ) == NULL ) {
864             pr->p_flags &= ~P_ACCOUNT;
865         } else {
866             pr->p_flags |= P_ACCOUNT;
867 #ifdef ABS_PRINT
868             if ( pr->p_role != NULL && pr->p_role != defprinter.p_role ) {
869                 free( pr->p_role );
870             }
871             a = area;
872             if (( p = pgetstr( "ro", &a )) == NULL ) {
873                 pr->p_role = defprinter.p_role;
874             } else {
875                 if (( pr->p_role =
876                         (char *)malloc( strlen( p ) + 1 )) == NULL ) {
877                     LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
878                     exit( 1 );
879                 }
880                 strcpy( pr->p_role, p );
881             }
882
883             if (( c = pgetnum( "si" )) < 0 ) {
884                 pr->p_srvid = defprinter.p_srvid;
885             } else {
886                 pr->p_srvid = c;
887             }
888 #endif /* ABS_PRINT */
889         }
890
891
892         /*
893          * Cost of printer.
894          */
895         if ( pr->p_pagecost_msg != NULL &&
896                 pr->p_pagecost_msg != defprinter.p_pagecost_msg ) {
897             free( pr->p_pagecost_msg );
898         }
899         a = area;
900         if (( p = pgetstr( "pc", &a )) != NULL ) {
901             if (( pr->p_pagecost_msg =
902                     (char *)malloc( strlen( p ) + 1 )) == NULL ) {
903                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
904                 exit( 1 );
905             }
906             strcpy( pr->p_pagecost_msg, p );
907             pr->p_pagecost = 0;
908         } else if ( pr->p_flags & P_ACCOUNT ) {
909             if (( c = pgetnum( "pc" )) < 0 ) {
910                 pr->p_pagecost = defprinter.p_pagecost;
911             } else {
912                 pr->p_pagecost = c;
913             }
914             pr->p_pagecost_msg = NULL;
915         }
916
917         /*
918          * Get lpd lock file.
919          */
920         if ( pr->p_lock != NULL && pr->p_lock != defprinter.p_lock ) {
921             free( pr->p_lock );
922         }
923         a = area;
924         if (( p = pgetstr( "lo", &a )) == NULL ) {
925             pr->p_lock = defprinter.p_lock;
926         } else {
927             if (( pr->p_lock = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
928                 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
929                 exit( 1 );
930             }
931             strcpy( pr->p_lock, p );
932         }
933
934 #ifdef KRB
935         /*
936          * Must Kerberos authenticate?
937          */
938         if ( pgetflag( "ka" ) == 1 ) {
939             pr->p_flags |= P_KRB;
940         } else {
941             pr->p_flags &= ~P_KRB;
942         }
943 #endif /* KRB */
944
945         endprent();
946     }
947 #endif /* HAVE_CUPS */
948
949     return( 0 );
950 }