]> arthur.barton.de Git - netatalk.git/blob - etc/papd/main.c
Initial revision
[netatalk.git] / etc / papd / main.c
1 /*
2  * Copyright (c) 1990,1995 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #include <sys/param.h>
7 #include <sys/types.h>
8 #include <sys/time.h>
9 #include <sys/uio.h>
10 #if defined( sun ) && defined( __svr4__ )
11 #include </usr/ucbinclude/sys/file.h>
12 #else sun __svr4__
13 #include <sys/file.h>
14 #endif sun __svr4__
15 #include <sys/socket.h>
16 #include <sys/syslog.h>
17 #include <sys/wait.h>
18 #include <errno.h>
19
20 #include <string.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <netdb.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27
28 #include <netatalk/endian.h>
29 #include <netatalk/at.h>
30 #include <atalk/compat.h>
31 #include <atalk/atp.h>
32 #include <atalk/pap.h>
33 #include <atalk/paths.h>
34 #include <atalk/util.h>
35
36 #include "printer.h"
37
38 #define _PATH_PAPDPPDFILE       ".ppd"
39
40 #define PIPED_STATUS    "status: print spooler processing job"
41
42 struct printer  defprinter;
43 struct printer  *printers = NULL;
44
45 int             debug = 0;
46 char            *conffile = _PATH_PAPDCONF;
47 char            *printcap = _PATH_PAPDPRINTCAP;
48 unsigned char   connid, quantum, sock, oquantum = PAP_MAXQUANTUM;
49 char            *cannedstatus = PIPED_STATUS;
50 struct printer  *printer = NULL;
51 char            *version = VERSION;
52 static char      *pidfile = _PATH_PAPDLOCK;
53
54 /* this only needs to be used by the server process */
55 static void papd_exit(const int i)
56 {
57   server_unlock(pidfile);
58   exit(i);
59 }
60
61 #if !defined( ibm032 ) && !defined( _IBMR2 )
62     void
63 #endif ibm032 _IBMR2
64 die( n )
65     int                 n;
66 {
67     struct printer      *pr;
68
69     for ( pr = printers; pr; pr = pr->p_next ) {
70         if ( pr->p_flags & P_REGISTERED ) {
71             if ( nbp_unrgstr( pr->p_name, pr->p_type, pr->p_zone ) < 0 ) {
72                 syslog( LOG_ERR, "can't unregister %s:%s@%s\n", pr->p_name,
73                         pr->p_type, pr->p_zone );
74                 papd_exit( n + 1 );
75             }
76             syslog( LOG_ERR, "unregister %s:%s@%s\n", pr->p_name, pr->p_type,
77                     pr->p_zone );
78         }
79     }
80     papd_exit( n );
81 }
82
83 #if !defined( ibm032 ) && !defined( _IBMR2 )
84     void
85 #endif ibm032 _IBMR2
86 reap()
87 {
88     int         status;
89     int         pid;
90
91     while (( pid = wait3( &status, WNOHANG, 0 )) > 0 ) {
92         if ( WIFEXITED( status )) {
93             if ( WEXITSTATUS( status )) {
94                 syslog( LOG_ERR, "child %d exited with %d", pid,
95                         WEXITSTATUS( status ));
96             } else {
97                 syslog( LOG_INFO, "child %d done", pid );
98             }
99         } else {
100             if ( WIFSIGNALED( status )) {
101                 syslog( LOG_ERR, "child %d killed with %d", pid,
102                         WTERMSIG( status ));
103             } else {
104                 syslog( LOG_ERR, "child %d died", pid );
105             }
106         }
107     }
108     return;
109 }
110
111 char            rbuf[ 255 + 1 + 8 ];
112
113 main( ac, av )
114     int         ac;
115     char        **av;
116 {
117     extern char         *optarg;
118     extern int          optind;
119
120     ATP                 atp;
121     struct atp_block    atpb;
122     struct sockaddr_at  sat;
123     struct sigaction    sv;
124     struct iovec        iov;
125     fd_set              fdset;
126     struct printer      *pr;
127     char                *p, hostname[ MAXHOSTNAMELEN ];
128     char                cbuf[ 8 ];
129     int                 c;
130
131     if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
132         perror( "gethostname" );
133         exit( 1 );
134     }
135     if (( p = strchr( hostname, '.' )) != 0 ) {
136         *p = '\0';
137     }
138     if (( defprinter.p_name = (char *)malloc( strlen( hostname ) + 1 ))
139             == NULL ) {
140         perror( "malloc" );
141         exit( 1 );
142     }
143     strcpy( defprinter.p_name, hostname );
144     defprinter.p_type = "LaserWriter";
145     defprinter.p_zone = "*";
146     memset(&defprinter.p_addr, 0, sizeof(defprinter.p_addr));
147     defprinter.p_ppdfile = _PATH_PAPDPPDFILE;
148 #ifdef __svr4__
149     defprinter.p_flags = P_PIPED;
150     defprinter.p_printer = "/usr/bin/lp -T PS";
151 #else
152     defprinter.p_flags = P_SPOOLED;
153     defprinter.p_printer = "lp";
154 #endif
155     defprinter.p_operator = "operator";
156     defprinter.p_spool = _PATH_PAPDSPOOLDIR;
157 #ifdef ABS_PRINT
158     defprinter.p_role = NULL;
159     defprinter.p_srvid = 0;
160 #endif ABS_PRINT
161     defprinter.p_pagecost = 200;                /* default cost */
162     defprinter.p_pagecost_msg = NULL;
163     defprinter.p_lock = "lock";
164
165     while (( c = getopt( ac, av, "adf:p:P:" )) != EOF ) {
166         switch ( c ) {
167         case 'a' :              /* for compatibility with old papd */
168             break;
169
170         case 'd' :              /* debug */
171             debug++;
172             break;
173
174         case 'f' :              /* conffile */
175             conffile = optarg;
176             break;
177
178         case 'p' :              /* printcap */
179             printcap = optarg;
180             break;
181
182         case 'P' :
183             pidfile = optarg;
184             break;
185
186         default :
187             fprintf( stderr,
188                     "Usage:\t%s [ -d ] [ -f conffile ] [ -p printcap ]\n",
189                     *av );
190             exit( 1 );
191         }
192     }
193
194     getprinters( conffile );
195
196     switch (server_lock("papd", pidfile, debug)) {
197     case 0: /* open a couple things again in the child */
198       if ((c = open("/", O_RDONLY)) >= 0) {
199         dup2(c, 1);
200         dup2(c, 2);
201       }
202       break;
203     case -1:
204       exit(1);
205     default:
206       exit(0);
207     }      
208
209     /*
210      * Start logging.
211      */
212     if (( p = strrchr( av[ 0 ], '/' )) == NULL ) {
213         p = av[ 0 ];
214     } else {
215         p++;
216     }
217 #ifdef ultrix
218     openlog( p, LOG_PID );
219 #else ultrix
220     openlog( p, LOG_NDELAY|LOG_PID, LOG_LPR );
221 #endif ultrix
222
223     syslog( LOG_INFO, "restart (%s)", version );
224
225     for ( pr = printers; pr; pr = pr->p_next ) {
226         if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) < 0 ) {
227             syslog( LOG_ERR, "printcap problem: %s", pr->p_printer );
228         }
229         if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) {
230             syslog( LOG_ERR, "atp_open: %m" );
231             papd_exit( 1 );
232         }
233         if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type,
234                 pr->p_zone ) < 0 ) {
235             syslog( LOG_ERR, "can't register %s:%s@%s", pr->p_name, pr->p_type,
236                     pr->p_zone );
237             die( 1 );
238         }
239         syslog( LOG_INFO, "register %s:%s@%s", pr->p_name, pr->p_type,
240                 pr->p_zone );
241         pr->p_flags |= P_REGISTERED;
242     }
243
244     memset(&sv, 0, sizeof(sv));
245     sv.sa_handler = die;
246     sigemptyset( &sv.sa_mask );
247     sv.sa_flags = SA_RESTART;
248     if ( sigaction( SIGTERM, &sv, 0 ) < 0 ) {
249         syslog( LOG_ERR, "sigaction: %m" );
250         papd_exit( 1 );
251     }
252
253     sv.sa_handler = reap;
254     sigemptyset( &sv.sa_mask );
255     sv.sa_flags = SA_RESTART;
256     if ( sigaction( SIGCHLD, &sv, 0 ) < 0 ) {
257         syslog( LOG_ERR, "sigaction: %m" );
258         papd_exit( 1 );
259     }
260
261     /*
262      * Begin accepting connections.
263      */
264     FD_ZERO( &fdset );
265     for (;;) {
266         for ( pr = printers; pr; pr = pr->p_next ) {
267             FD_SET( atp_fileno( pr->p_atp ), &fdset );
268         }
269         if (( c = select( FD_SETSIZE, &fdset, 0, 0, 0 )) < 0 ) {
270             if ( errno == EINTR ) {
271                 continue;
272             }
273             syslog( LOG_ERR, "select: %m" );
274             papd_exit( 1 );
275         }
276
277         for ( pr = printers; pr; pr = pr->p_next ) {
278             if ( FD_ISSET( atp_fileno( pr->p_atp ), &fdset )) {
279                 int             err = 0;
280
281                 bzero( &sat, sizeof( struct sockaddr_at ));
282 #ifdef BSD4_4
283                 sat.sat_len = sizeof( struct sockaddr_at );
284 #endif BSD4_4
285                 sat.sat_family = AF_APPLETALK;
286                 sat.sat_addr.s_net = ATADDR_ANYNET;
287                 sat.sat_addr.s_node = ATADDR_ANYNODE;
288                 sat.sat_port = ATADDR_ANYPORT;
289                 /* do an atp_rsel(), to prevent hangs */
290                 if (( c = atp_rsel( pr->p_atp, &sat, ATP_TREQ )) != ATP_TREQ ) {
291                     continue;
292                 }
293                 atpb.atp_saddr = &sat;
294                 atpb.atp_rreqdata = cbuf;
295                 atpb.atp_rreqdlen = sizeof( cbuf );
296                 if ( atp_rreq( pr->p_atp, &atpb ) < 0 ) {
297                     syslog( LOG_ERR, "atp_rreq: %m" );
298                     continue;
299                 }
300
301                 /* should check length of req buf */
302
303                 switch( cbuf[ 1 ] ) {
304                 case PAP_OPEN :
305                     connid = (unsigned char)cbuf[ 0 ];
306                     sock = (unsigned char)cbuf[ 4 ];
307                     quantum = (unsigned char)cbuf[ 5 ];
308                     rbuf[ 0 ] = cbuf[ 0 ];
309                     rbuf[ 1 ] = PAP_OPENREPLY;
310                     rbuf[ 2 ] = rbuf[ 3 ] = 0;
311
312                     if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) != 0 ) {
313                         syslog( LOG_ERR, "printcap problem: %s",
314                                 pr->p_printer );
315                         rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
316                         err = 1;
317                     }
318
319                     /*
320                      * If this fails, we've run out of sockets. Rather than
321                      * just die(), let's try to continue. Maybe some sockets
322                      * will close, and we can continue;
323                      */
324                     if (( atp = atp_open( ATADDR_ANYPORT, 
325                                           &pr->p_addr)) == NULL ) {
326                         syslog( LOG_ERR, "atp_open: %m" );
327                         rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
328                         err = 1;
329                     }
330                     rbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
331                     rbuf[ 5 ] = oquantum;
332                     rbuf[ 6 ] = rbuf[ 7 ] = 0;
333
334                     iov.iov_base = rbuf;
335                     iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
336                     atpb.atp_sresiov = &iov;
337                     atpb.atp_sresiovcnt = 1;
338                     /*
339                      * This may error out if we lose a route, so we won't die().
340                      */
341                     if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
342                         syslog( LOG_ERR, "atp_sresp: %m" );
343                         continue;
344                     }
345
346                     if ( err ) {
347                         continue;
348                     }
349
350                     switch ( c = fork()) {
351                     case -1 :
352                         syslog( LOG_ERR, "fork: %m" );
353                         continue;
354
355                     case 0 : /* child */
356                         printer = pr;
357
358                         if (( printer->p_flags & P_SPOOLED ) &&
359                                 chdir( printer->p_spool ) < 0 ) {
360                             syslog( LOG_ERR, "chdir %s: %m", printer->p_spool );
361                             exit( 1 );
362                         }
363
364                         sv.sa_handler = SIG_DFL;
365                         sigemptyset( &sv.sa_mask );
366                         sv.sa_flags = SA_RESTART;
367                         if ( sigaction( SIGTERM, &sv, 0 ) < 0 ) {
368                             syslog( LOG_ERR, "sigaction: %m" );
369                             exit( 1 );
370                         }
371
372                         for ( pr = printers; pr; pr = pr->p_next ) {
373                             atp_close( pr->p_atp );
374                         }
375                         sat.sat_port = sock;
376                         if ( session( atp, &sat ) < 0 ) {
377                             syslog( LOG_ERR, "bad session" );
378                             exit( 1 );
379                         }
380                         exit( 0 );
381                         break;
382
383                     default : /* parent */
384                         syslog( LOG_INFO, "child %d for \"%s\" from %u.%u",
385                                 c, pr->p_name, ntohs( sat.sat_addr.s_net ),
386                                 sat.sat_addr.s_node);
387                         atp_close( atp );
388                     }
389                     break;
390
391                 case PAP_SENDSTATUS :
392                     rbuf[ 0 ] = 0;
393                     rbuf[ 1 ] = PAP_STATUS;
394                     rbuf[ 2 ] = rbuf[ 3 ] = 0;
395                     rbuf[ 4 ] = rbuf[ 5 ] = 0;
396                     rbuf[ 6 ] = rbuf[ 7 ] = 0;
397
398                     iov.iov_base = rbuf;
399                     iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
400                     atpb.atp_sresiov = &iov;
401                     atpb.atp_sresiovcnt = 1;
402                     /*
403                      * This may error out if we lose a route, so we won't die().
404                      */
405                     if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
406                         syslog( LOG_ERR, "atp_sresp: %m" );
407                     }
408                     break;
409
410                 default :
411                     syslog( LOG_ERR, "Bad request from %u.%u!",
412                             ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node );
413                     continue;
414                     break;
415                 }
416
417 #ifdef notdef
418                 /*
419                  * Sometimes the child process will send its first READ
420                  * before the parent has sent the OPEN REPLY.  Moving this
421                  * code into the OPEN/STATUS switch fixes this problem.
422                  */
423                 iov.iov_base = rbuf;
424                 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
425                 atpb.atp_sresiov = &iov;
426                 atpb.atp_sresiovcnt = 1;
427                 /*
428                  * This may error out if we lose a route, so we won't die().
429                  */
430                 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
431                     syslog( LOG_ERR, "atp_sresp: %m" );
432                 }
433 #endif notdef
434             }
435         }
436     }
437 }
438
439 /*
440  * We assume buf is big enough for 255 bytes of data and a length byte.
441  */
442     int
443 getstatus( pr, buf )
444     struct printer      *pr;
445     char                *buf;
446 {
447     char                path[ MAXPATHLEN ];
448     int                 fd = -1, rc;
449
450     if ( pr->p_flags & P_SPOOLED && ( pr->p_spool != NULL )) {
451         strcpy( path, pr->p_spool );
452         strcat( path, "/status" );
453         fd = open( path, O_RDONLY);
454     }
455
456     if (( pr->p_flags & P_PIPED ) || ( fd < 0 )) {
457         *buf = strlen( cannedstatus );
458         strncpy( &buf[ 1 ], cannedstatus, *buf );
459         return( *buf + 1 );
460     } else {
461         if (( rc = read( fd, &buf[ 1 ], 255 )) < 0 ) {
462             rc = 0;
463         }
464         close( fd );
465         if ( rc && buf[ rc ] == '\n' ) {        /* remove trailing newline */
466             rc--;
467         }
468         *buf = rc;
469         return( rc + 1 );
470     }
471 }
472
473 char    *pgetstr();
474 char    *getpname();
475
476 getprinters( cf )
477     char        *cf;
478 {
479     char                buf[ 1024 ], area[ 1024 ], *a, *p, *name, *type, *zone;
480     struct printer      *pr;
481     int                 c;
482
483     while (( c = getprent( cf, buf )) > 0 ) {
484         a = area;
485         /*
486          * Get the printer's nbp name.
487          */
488         if (( p = getpname( &a )) == NULL ) {
489             fprintf( stderr, "No printer name\n" );
490             exit( 1 );
491         }
492
493         if (( pr = (struct printer *)malloc( sizeof( struct printer )))
494                 == NULL ) {
495             perror( "malloc" );
496             exit( 1 );
497         }
498         bzero( pr, sizeof( struct printer ));
499
500         name = defprinter.p_name;
501         type = defprinter.p_type;
502         zone = defprinter.p_zone;
503         if ( nbp_name( p, &name, &type, &zone )) {
504             fprintf( stderr, "Can't parse \"%s\"\n", name );
505             exit( 1 );
506         }
507         if ( name != defprinter.p_name ) {
508             if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) {
509                 perror( "malloc" );
510                 exit( 1 );
511             }
512             strcpy( pr->p_name, name );
513         } else {
514             pr->p_name = name;
515         }
516         if ( type != defprinter.p_type ) {
517             if (( pr->p_type = (char *)malloc( strlen( type ) + 1 )) == NULL ) {
518                 perror( "malloc" );
519                 exit( 1 );
520             }
521             strcpy( pr->p_type, type );
522         } else {
523             pr->p_type = type;
524         }
525         if ( zone != defprinter.p_zone ) {
526             if (( pr->p_zone = (char *)malloc( strlen( zone ) + 1 )) == NULL ) {
527                 perror( "malloc" );
528                 exit( 1 );
529             }
530             strcpy( pr->p_zone, zone );
531         } else {
532             pr->p_zone = zone;
533         }
534
535         if ( pnchktc( cf ) != 1 ) {
536             fprintf( stderr, "Bad papcap entry\n" );
537             exit( 1 );
538         }
539
540         /*
541          * Get PPD file.
542          */
543         if (( p = pgetstr( "pd", &a )) == NULL ) {
544             pr->p_ppdfile = defprinter.p_ppdfile;
545         } else {
546             if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
547                 perror( "malloc" );
548                 exit( 1 );
549             }
550             strcpy( pr->p_ppdfile, p );
551         }
552
553         /*
554          * Get lpd printer name.
555          */
556         if (( p = pgetstr( "pr", &a )) == NULL ) {
557             pr->p_printer = defprinter.p_printer;
558             pr->p_flags = defprinter.p_flags;
559         } else {
560             if ( *p == '|' ) {
561                 p++;
562                 pr->p_flags = P_PIPED;
563             } else {
564                 pr->p_flags = P_SPOOLED;
565             }
566             if (( pr->p_printer = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
567                 perror( "malloc" );
568                 exit( 1 );
569             }
570             strcpy( pr->p_printer, p );
571         }
572
573         if ( pr->p_flags & P_SPOOLED ) {
574             /*
575              * Get operator name.
576              */
577             if (( p = pgetstr( "op", &a )) == NULL ) {
578                 pr->p_operator = defprinter.p_operator;
579             } else {
580                 if (( pr->p_operator = (char *)malloc( strlen( p ) + 1 ))
581                         == NULL ) {
582                     perror( "malloc" );
583                     exit( 1 );
584                 }
585                 strcpy( pr->p_operator, p );
586             }
587         }
588
589         /* get printer's appletalk address. */
590         if (( p = pgetstr( "pa", &a )) == NULL ) 
591             memcpy(&pr->p_addr, &defprinter.p_addr, sizeof(pr->p_addr));
592         else 
593             atalk_aton(p, &pr->p_addr);
594
595         pr->p_next = printers;
596         printers = pr;
597     }
598     if ( c == 0 ) {
599         endprent();
600     } else {                    /* No capability file, do default */
601         printers = &defprinter;
602     }
603 }
604
605 rprintcap( pr )
606     struct printer      *pr;
607 {
608     char                buf[ 1024 ], area[ 1024 ], *a, *p;
609     int                 c;
610
611     /*
612      * Spool directory from printcap file.
613      */
614     if ( pr->p_flags & P_SPOOLED ) {
615         if ( pgetent( printcap, buf, pr->p_printer ) != 1 ) {
616             syslog( LOG_ERR, "No such printer: %s", pr->p_printer );
617             return( -1 );
618         }
619
620         /*
621          * Spool directory.
622          */
623         if ( pr->p_spool != NULL && pr->p_spool != defprinter.p_spool ) {
624             free( pr->p_spool );
625         }
626         a = area;
627         if (( p = pgetstr( "sd", &a )) == NULL ) {
628             pr->p_spool = defprinter.p_spool;
629         } else {
630             if (( pr->p_spool = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
631                 syslog( LOG_ERR, "malloc: %m" );
632                 exit( 1 );
633             }
634             strcpy( pr->p_spool, p );
635         }
636
637         /*
638          * Is accounting on?
639          */
640         a = area;
641         if ( pgetstr( "af", &a ) == NULL ) {
642             pr->p_flags &= ~P_ACCOUNT;
643         } else {
644             pr->p_flags |= P_ACCOUNT;
645 #ifdef ABS_PRINT
646             if ( pr->p_role != NULL && pr->p_role != defprinter.p_role ) {
647                 free( pr->p_role );
648             }
649             a = area;
650             if (( p = pgetstr( "ro", &a )) == NULL ) {
651                 pr->p_role = defprinter.p_role;
652             } else {
653                 if (( pr->p_role =
654                         (char *)malloc( strlen( p ) + 1 )) == NULL ) {
655                     syslog( LOG_ERR, "malloc: %m" );
656                     exit( 1 );
657                 }
658                 strcpy( pr->p_role, p );
659             }
660
661             if (( c = pgetnum( "si" )) < 0 ) {
662                 pr->p_srvid = defprinter.p_srvid;
663             } else {
664                 pr->p_srvid = c;
665             }
666 #endif ABS_PRINT
667         }
668
669
670         /*
671          * Cost of printer.
672          */
673         if ( pr->p_pagecost_msg != NULL &&
674                 pr->p_pagecost_msg != defprinter.p_pagecost_msg ) {
675             free( pr->p_pagecost_msg );
676         }
677         a = area;
678         if (( p = pgetstr( "pc", &a )) != NULL ) {
679             if (( pr->p_pagecost_msg =
680                     (char *)malloc( strlen( p ) + 1 )) == NULL ) {
681                 syslog( LOG_ERR, "malloc: %m" );
682                 exit( 1 );
683             }
684             strcpy( pr->p_pagecost_msg, p );
685             pr->p_pagecost = 0;
686         } else if ( pr->p_flags & P_ACCOUNT ) {
687             if (( c = pgetnum( "pc" )) < 0 ) {
688                 pr->p_pagecost = defprinter.p_pagecost;
689             } else {
690                 pr->p_pagecost = c;
691             }
692             pr->p_pagecost_msg = NULL;
693         }
694
695         /*
696          * Get lpd lock file.
697          */
698         if ( pr->p_lock != NULL && pr->p_lock != defprinter.p_lock ) {
699             free( pr->p_lock );
700         }
701         a = area;
702         if (( p = pgetstr( "lo", &a )) == NULL ) {
703             pr->p_lock = defprinter.p_lock;
704         } else {
705             if (( pr->p_lock = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
706                 syslog( LOG_ERR, "malloc: %m" );
707                 exit( 1 );
708             }
709             strcpy( pr->p_lock, p );
710         }
711
712 #ifdef KRB
713         /*
714          * Must Kerberos authenticate?
715          */
716         if ( pgetflag( "ka" ) == 1 ) {
717             pr->p_flags |= P_AUTH;
718         } else {
719             pr->p_flags &= ~P_AUTH;
720         }
721 #endif
722
723         endprent();
724     }
725
726     return( 0 );
727 }