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