2 * Copyright (c) 1990,1995 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
10 #if defined( sun ) && defined( __svr4__ )
11 #include </usr/ucbinclude/sys/file.h>
15 #include <sys/socket.h>
16 #include <sys/syslog.h>
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>
38 #define _PATH_PAPDPPDFILE ".ppd"
40 #define PIPED_STATUS "status: print spooler processing job"
42 struct printer defprinter;
43 struct printer *printers = NULL;
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;
54 /* this only needs to be used by the server process */
55 static void papd_exit(const int i)
57 server_unlock(pidfile);
61 #if !defined( ibm032 ) && !defined( _IBMR2 )
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 );
76 syslog( LOG_ERR, "unregister %s:%s@%s\n", pr->p_name, pr->p_type,
83 #if !defined( ibm032 ) && !defined( _IBMR2 )
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 ));
97 syslog( LOG_INFO, "child %d done", pid );
100 if ( WIFSIGNALED( status )) {
101 syslog( LOG_ERR, "child %d killed with %d", pid,
104 syslog( LOG_ERR, "child %d died", pid );
111 char rbuf[ 255 + 1 + 8 ];
121 struct atp_block atpb;
122 struct sockaddr_at sat;
127 char *p, hostname[ MAXHOSTNAMELEN ];
131 if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
132 perror( "gethostname" );
135 if (( p = strchr( hostname, '.' )) != 0 ) {
138 if (( defprinter.p_name = (char *)malloc( strlen( hostname ) + 1 ))
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;
149 defprinter.p_flags = P_PIPED;
150 defprinter.p_printer = "/usr/bin/lp -T PS";
152 defprinter.p_flags = P_SPOOLED;
153 defprinter.p_printer = "lp";
155 defprinter.p_operator = "operator";
156 defprinter.p_spool = _PATH_PAPDSPOOLDIR;
158 defprinter.p_role = NULL;
159 defprinter.p_srvid = 0;
161 defprinter.p_pagecost = 200; /* default cost */
162 defprinter.p_pagecost_msg = NULL;
163 defprinter.p_lock = "lock";
165 while (( c = getopt( ac, av, "adf:p:P:" )) != EOF ) {
167 case 'a' : /* for compatibility with old papd */
170 case 'd' : /* debug */
174 case 'f' : /* conffile */
178 case 'p' : /* printcap */
188 "Usage:\t%s [ -d ] [ -f conffile ] [ -p printcap ]\n",
194 getprinters( conffile );
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) {
212 if (( p = strrchr( av[ 0 ], '/' )) == NULL ) {
218 openlog( p, LOG_PID );
220 openlog( p, LOG_NDELAY|LOG_PID, LOG_LPR );
223 syslog( LOG_INFO, "restart (%s)", version );
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 );
229 if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) {
230 syslog( LOG_ERR, "atp_open: %m" );
233 if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type,
235 syslog( LOG_ERR, "can't register %s:%s@%s", pr->p_name, pr->p_type,
239 syslog( LOG_INFO, "register %s:%s@%s", pr->p_name, pr->p_type,
241 pr->p_flags |= P_REGISTERED;
244 memset(&sv, 0, sizeof(sv));
246 sigemptyset( &sv.sa_mask );
247 sv.sa_flags = SA_RESTART;
248 if ( sigaction( SIGTERM, &sv, 0 ) < 0 ) {
249 syslog( LOG_ERR, "sigaction: %m" );
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" );
262 * Begin accepting connections.
266 for ( pr = printers; pr; pr = pr->p_next ) {
267 FD_SET( atp_fileno( pr->p_atp ), &fdset );
269 if (( c = select( FD_SETSIZE, &fdset, 0, 0, 0 )) < 0 ) {
270 if ( errno == EINTR ) {
273 syslog( LOG_ERR, "select: %m" );
277 for ( pr = printers; pr; pr = pr->p_next ) {
278 if ( FD_ISSET( atp_fileno( pr->p_atp ), &fdset )) {
281 bzero( &sat, sizeof( struct sockaddr_at ));
283 sat.sat_len = sizeof( struct sockaddr_at );
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 ) {
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" );
301 /* should check length of req buf */
303 switch( cbuf[ 1 ] ) {
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;
312 if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) != 0 ) {
313 syslog( LOG_ERR, "printcap problem: %s",
315 rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
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;
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;
330 rbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
331 rbuf[ 5 ] = oquantum;
332 rbuf[ 6 ] = rbuf[ 7 ] = 0;
335 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
336 atpb.atp_sresiov = &iov;
337 atpb.atp_sresiovcnt = 1;
339 * This may error out if we lose a route, so we won't die().
341 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
342 syslog( LOG_ERR, "atp_sresp: %m" );
350 switch ( c = fork()) {
352 syslog( LOG_ERR, "fork: %m" );
358 if (( printer->p_flags & P_SPOOLED ) &&
359 chdir( printer->p_spool ) < 0 ) {
360 syslog( LOG_ERR, "chdir %s: %m", printer->p_spool );
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" );
372 for ( pr = printers; pr; pr = pr->p_next ) {
373 atp_close( pr->p_atp );
376 if ( session( atp, &sat ) < 0 ) {
377 syslog( LOG_ERR, "bad session" );
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);
391 case PAP_SENDSTATUS :
393 rbuf[ 1 ] = PAP_STATUS;
394 rbuf[ 2 ] = rbuf[ 3 ] = 0;
395 rbuf[ 4 ] = rbuf[ 5 ] = 0;
396 rbuf[ 6 ] = rbuf[ 7 ] = 0;
399 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
400 atpb.atp_sresiov = &iov;
401 atpb.atp_sresiovcnt = 1;
403 * This may error out if we lose a route, so we won't die().
405 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
406 syslog( LOG_ERR, "atp_sresp: %m" );
411 syslog( LOG_ERR, "Bad request from %u.%u!",
412 ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node );
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.
424 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
425 atpb.atp_sresiov = &iov;
426 atpb.atp_sresiovcnt = 1;
428 * This may error out if we lose a route, so we won't die().
430 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
431 syslog( LOG_ERR, "atp_sresp: %m" );
440 * We assume buf is big enough for 255 bytes of data and a length byte.
447 char path[ MAXPATHLEN ];
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);
456 if (( pr->p_flags & P_PIPED ) || ( fd < 0 )) {
457 *buf = strlen( cannedstatus );
458 strncpy( &buf[ 1 ], cannedstatus, *buf );
461 if (( rc = read( fd, &buf[ 1 ], 255 )) < 0 ) {
465 if ( rc && buf[ rc ] == '\n' ) { /* remove trailing newline */
479 char buf[ 1024 ], area[ 1024 ], *a, *p, *name, *type, *zone;
483 while (( c = getprent( cf, buf )) > 0 ) {
486 * Get the printer's nbp name.
488 if (( p = getpname( &a )) == NULL ) {
489 fprintf( stderr, "No printer name\n" );
493 if (( pr = (struct printer *)malloc( sizeof( struct printer )))
498 bzero( pr, sizeof( struct printer ));
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 );
507 if ( name != defprinter.p_name ) {
508 if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) {
512 strcpy( pr->p_name, name );
516 if ( type != defprinter.p_type ) {
517 if (( pr->p_type = (char *)malloc( strlen( type ) + 1 )) == NULL ) {
521 strcpy( pr->p_type, type );
525 if ( zone != defprinter.p_zone ) {
526 if (( pr->p_zone = (char *)malloc( strlen( zone ) + 1 )) == NULL ) {
530 strcpy( pr->p_zone, zone );
535 if ( pnchktc( cf ) != 1 ) {
536 fprintf( stderr, "Bad papcap entry\n" );
543 if (( p = pgetstr( "pd", &a )) == NULL ) {
544 pr->p_ppdfile = defprinter.p_ppdfile;
546 if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
550 strcpy( pr->p_ppdfile, p );
554 * Get lpd printer name.
556 if (( p = pgetstr( "pr", &a )) == NULL ) {
557 pr->p_printer = defprinter.p_printer;
558 pr->p_flags = defprinter.p_flags;
562 pr->p_flags = P_PIPED;
564 pr->p_flags = P_SPOOLED;
566 if (( pr->p_printer = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
570 strcpy( pr->p_printer, p );
573 if ( pr->p_flags & P_SPOOLED ) {
577 if (( p = pgetstr( "op", &a )) == NULL ) {
578 pr->p_operator = defprinter.p_operator;
580 if (( pr->p_operator = (char *)malloc( strlen( p ) + 1 ))
585 strcpy( pr->p_operator, p );
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));
593 atalk_aton(p, &pr->p_addr);
595 pr->p_next = printers;
600 } else { /* No capability file, do default */
601 printers = &defprinter;
608 char buf[ 1024 ], area[ 1024 ], *a, *p;
612 * Spool directory from printcap file.
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 );
623 if ( pr->p_spool != NULL && pr->p_spool != defprinter.p_spool ) {
627 if (( p = pgetstr( "sd", &a )) == NULL ) {
628 pr->p_spool = defprinter.p_spool;
630 if (( pr->p_spool = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
631 syslog( LOG_ERR, "malloc: %m" );
634 strcpy( pr->p_spool, p );
641 if ( pgetstr( "af", &a ) == NULL ) {
642 pr->p_flags &= ~P_ACCOUNT;
644 pr->p_flags |= P_ACCOUNT;
646 if ( pr->p_role != NULL && pr->p_role != defprinter.p_role ) {
650 if (( p = pgetstr( "ro", &a )) == NULL ) {
651 pr->p_role = defprinter.p_role;
654 (char *)malloc( strlen( p ) + 1 )) == NULL ) {
655 syslog( LOG_ERR, "malloc: %m" );
658 strcpy( pr->p_role, p );
661 if (( c = pgetnum( "si" )) < 0 ) {
662 pr->p_srvid = defprinter.p_srvid;
673 if ( pr->p_pagecost_msg != NULL &&
674 pr->p_pagecost_msg != defprinter.p_pagecost_msg ) {
675 free( pr->p_pagecost_msg );
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" );
684 strcpy( pr->p_pagecost_msg, p );
686 } else if ( pr->p_flags & P_ACCOUNT ) {
687 if (( c = pgetnum( "pc" )) < 0 ) {
688 pr->p_pagecost = defprinter.p_pagecost;
692 pr->p_pagecost_msg = NULL;
698 if ( pr->p_lock != NULL && pr->p_lock != defprinter.p_lock ) {
702 if (( p = pgetstr( "lo", &a )) == NULL ) {
703 pr->p_lock = defprinter.p_lock;
705 if (( pr->p_lock = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
706 syslog( LOG_ERR, "malloc: %m" );
709 strcpy( pr->p_lock, p );
714 * Must Kerberos authenticate?
716 if ( pgetflag( "ka" ) == 1 ) {
717 pr->p_flags |= P_AUTH;
719 pr->p_flags &= ~P_AUTH;