2 * $Id: main.c,v 1.17 2002-09-29 23:29:14 sibaz Exp $
4 * Copyright (c) 1990,1995 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
12 #include <sys/param.h>
15 #if defined( sun ) && defined( __svr4__ )
16 #include </usr/ucbinclude/sys/file.h>
17 #else /* sun && __svr4__ */
19 #endif /* sun && __svr4__ */
20 #include <sys/socket.h>
21 #include <atalk/logger.h>
23 /* POSIX.1 sys/wait.h check */
24 #include <sys/types.h>
25 #ifdef HAVE_SYS_WAIT_H
27 #endif /* HAVE_SYS_WAIT_H */
29 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
30 #endif /* ! WEXITSTATUS */
32 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
33 #endif /* ! WIFEXITED */
40 #else /* STDC_HEADERS */
44 #endif /* HAVE_STRCHR */
45 char *strchr (), *strrchr ();
47 #define memcpy(d,s,n) bcopy ((s), (d), (n))
48 #define memmove(d,s,n) bcopy ((s), (d), (n))
49 #endif /* ! HAVE_MEMCPY */
50 #endif /* STDC_HEADERS */
59 #endif /* HAVE_UNISTD_H */
61 #include <netatalk/endian.h>
62 #include <netatalk/at.h>
63 #include <atalk/compat.h>
64 #include <atalk/atp.h>
65 #include <atalk/pap.h>
66 #include <atalk/paths.h>
67 #include <atalk/util.h>
68 #include <atalk/nbp.h>
75 #define _PATH_PAPDPPDFILE ".ppd"
77 #define PIPED_STATUS "status: print spooler processing job"
79 struct printer defprinter;
80 struct printer *printers = NULL;
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;
92 char *uampath = _PATH_PAPDUAMPATH;
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 );
100 /* this only needs to be used by the server process */
101 static void papd_exit(const int i)
103 server_unlock(pidfile);
108 #if !defined( ibm032 ) && !defined( _IBMR2 )
110 #endif /* ! ibm032 && ! _IBMR2 */
117 memset(&addr, 0, sizeof(addr));
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\n", pr->p_name,
123 pr->p_type, pr->p_zone );
126 LOG(log_error, logtype_papd, "unregister %s:%s@%s\n", pr->p_name, pr->p_type,
133 #if !defined( ibm032 ) && !defined( _IBMR2 )
135 #endif /* ! ibm032 && ! _IBMR2 */
141 while (( pid = wait3( &status, WNOHANG, 0 )) > 0 ) {
142 if ( WIFEXITED( status )) {
143 if ( WEXITSTATUS( status )) {
144 LOG(log_error, logtype_papd, "child %d exited with %d", pid,
145 WEXITSTATUS( status ));
147 LOG(log_info, logtype_papd, "child %d done", pid );
150 if ( WIFSIGNALED( status )) {
151 LOG(log_error, logtype_papd, "child %d killed with %d", pid,
154 LOG(log_error, logtype_papd, "child %d died", pid );
161 char rbuf[ 255 + 1 + 8 ];
170 struct atp_block atpb;
171 struct sockaddr_at sat;
176 char *p, hostname[ MAXHOSTNAMELEN ];
180 if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
181 perror( "gethostname" );
184 if (( p = strchr( hostname, '.' )) != 0 ) {
187 if (( defprinter.p_name = (char *)malloc( strlen( hostname ) + 1 ))
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 defprinter.p_ppdfile = _PATH_PAPDPPDFILE;
198 defprinter.p_flags = P_PIPED;
199 defprinter.p_printer = "/usr/bin/lp -T PS";
201 defprinter.p_flags = P_SPOOLED;
202 defprinter.p_printer = "lp";
203 #endif /* __svr4__ */
204 defprinter.p_operator = "operator";
205 defprinter.p_spool = _PATH_PAPDSPOOLDIR;
207 defprinter.p_role = NULL;
208 defprinter.p_srvid = 0;
209 #endif /* ABS_PRINT */
210 defprinter.p_pagecost = 200; /* default cost */
211 defprinter.p_pagecost_msg = NULL;
212 defprinter.p_lock = "lock";
214 while (( c = getopt( ac, av, "adf:p:P:v" )) != EOF ) {
216 case 'a' : /* for compatibility with old papd */
219 case 'd' : /* debug */
223 case 'f' : /* conffile */
227 case 'p' : /* printcap */
235 case 'v' : /* version */
236 printf( "papd (version %s)\n", VERSION );
242 "Usage:\t%s [ -d ] [ -f conffile ] [ -p printcap ]\n",
248 getprinters( conffile );
250 switch (server_lock("papd", pidfile, debug)) {
251 case 0: /* open a couple things again in the child */
252 if ((c = open("/", O_RDONLY)) >= 0) {
266 if (( p = strrchr( av[ 0 ], '/' )) == NULL ) {
272 openlog( p, LOG_PID );
275 syslog_setup(log_debug, logtype_default, logoption_ndelay|logoption_pid, logfacility_lpr );
278 LOG(log_info, logtype_papd, "restart (%s)", version );
280 for ( pr = printers; pr; pr = pr->p_next ) {
281 if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) < 0 ) {
282 LOG(log_error, logtype_papd, "printcap problem: %s", pr->p_printer );
284 if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) {
285 LOG(log_error, logtype_papd, "atp_open: %m" );
288 if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type,
290 LOG(log_error, logtype_papd, "can't register %s:%s@%s", pr->p_name, pr->p_type,
294 if ( pr->p_flags & P_AUTH ) {
295 LOG(log_info, logtype_papd, "Authentication enabled: %s", pr->p_name );
298 LOG(log_info, logtype_papd, "Authentication disabled: %s", pr->p_name );
300 LOG(log_info, logtype_papd, "register %s:%s@%s", pr->p_name, pr->p_type,
302 pr->p_flags |= P_REGISTERED;
305 memset(&sv, 0, sizeof(sv));
307 sigemptyset( &sv.sa_mask );
308 sv.sa_flags = SA_RESTART;
309 if ( sigaction( SIGTERM, &sv, 0 ) < 0 ) {
310 LOG(log_error, logtype_papd, "sigaction: %m" );
314 sv.sa_handler = reap;
315 sigemptyset( &sv.sa_mask );
316 sv.sa_flags = SA_RESTART;
317 if ( sigaction( SIGCHLD, &sv, 0 ) < 0 ) {
318 LOG(log_error, logtype_papd, "sigaction: %m" );
325 auth_load(uampath, uamlist);
328 * Begin accepting connections.
332 for ( pr = printers; pr; pr = pr->p_next ) {
333 FD_SET( atp_fileno( pr->p_atp ), &fdset );
335 if (( c = select( FD_SETSIZE, &fdset, 0, 0, 0 )) < 0 ) {
336 if ( errno == EINTR ) {
339 LOG(log_error, logtype_papd, "select: %m" );
343 for ( pr = printers; pr; pr = pr->p_next ) {
344 if ( FD_ISSET( atp_fileno( pr->p_atp ), &fdset )) {
347 memset( &sat, 0, sizeof( struct sockaddr_at ));
349 sat.sat_len = sizeof( struct sockaddr_at );
351 sat.sat_family = AF_APPLETALK;
352 sat.sat_addr.s_net = ATADDR_ANYNET;
353 sat.sat_addr.s_node = ATADDR_ANYNODE;
354 sat.sat_port = ATADDR_ANYPORT;
355 /* do an atp_rsel(), to prevent hangs */
356 if (( c = atp_rsel( pr->p_atp, &sat, ATP_TREQ )) != ATP_TREQ ) {
359 atpb.atp_saddr = &sat;
360 atpb.atp_rreqdata = cbuf;
361 atpb.atp_rreqdlen = sizeof( cbuf );
362 if ( atp_rreq( pr->p_atp, &atpb ) < 0 ) {
363 LOG(log_error, logtype_papd, "atp_rreq: %m" );
367 /* should check length of req buf */
369 switch( cbuf[ 1 ] ) {
371 connid = (unsigned char)cbuf[ 0 ];
372 sock = (unsigned char)cbuf[ 4 ];
373 quantum = (unsigned char)cbuf[ 5 ];
374 rbuf[ 0 ] = cbuf[ 0 ];
375 rbuf[ 1 ] = PAP_OPENREPLY;
376 rbuf[ 2 ] = rbuf[ 3 ] = 0;
378 if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) != 0 ) {
379 LOG(log_error, logtype_papd, "printcap problem: %s",
381 rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
386 * If this fails, we've run out of sockets. Rather than
387 * just die(), let's try to continue. Maybe some sockets
388 * will close, and we can continue;
390 if (( atp = atp_open( ATADDR_ANYPORT,
391 &pr->p_addr)) == NULL ) {
392 LOG(log_error, logtype_papd, "atp_open: %m" );
393 rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
396 rbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
397 rbuf[ 5 ] = oquantum;
398 rbuf[ 6 ] = rbuf[ 7 ] = 0;
401 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
402 atpb.atp_sresiov = &iov;
403 atpb.atp_sresiovcnt = 1;
405 * This may error out if we lose a route, so we won't die().
407 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
408 LOG(log_error, logtype_papd, "atp_sresp: %m" );
416 switch ( c = fork()) {
418 LOG(log_error, logtype_papd, "fork: %m" );
424 if (( printer->p_flags & P_SPOOLED ) &&
425 chdir( printer->p_spool ) < 0 ) {
426 LOG(log_error, logtype_papd, "chdir %s: %m", printer->p_spool );
430 sv.sa_handler = SIG_DFL;
431 sigemptyset( &sv.sa_mask );
432 sv.sa_flags = SA_RESTART;
433 if ( sigaction( SIGTERM, &sv, 0 ) < 0 ) {
434 LOG(log_error, logtype_papd, "sigaction: %m" );
438 for ( pr = printers; pr; pr = pr->p_next ) {
439 atp_close( pr->p_atp );
442 if ( session( atp, &sat ) < 0 ) {
443 LOG(log_error, logtype_papd, "bad session" );
449 default : /* parent */
450 LOG(log_info, logtype_papd, "child %d for \"%s\" from %u.%u",
451 c, pr->p_name, ntohs( sat.sat_addr.s_net ),
452 sat.sat_addr.s_node);
457 case PAP_SENDSTATUS :
459 rbuf[ 1 ] = PAP_STATUS;
460 rbuf[ 2 ] = rbuf[ 3 ] = 0;
461 rbuf[ 4 ] = rbuf[ 5 ] = 0;
462 rbuf[ 6 ] = rbuf[ 7 ] = 0;
465 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
466 atpb.atp_sresiov = &iov;
467 atpb.atp_sresiovcnt = 1;
469 * This may error out if we lose a route, so we won't die().
471 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
472 LOG(log_error, logtype_papd, "atp_sresp: %m" );
477 LOG(log_error, logtype_papd, "Bad request from %u.%u!",
478 ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node );
485 * Sometimes the child process will send its first READ
486 * before the parent has sent the OPEN REPLY. Moving this
487 * code into the OPEN/STATUS switch fixes this problem.
490 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
491 atpb.atp_sresiov = &iov;
492 atpb.atp_sresiovcnt = 1;
494 * This may error out if we lose a route, so we won't die().
496 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
497 LOG(log_error, logtype_papd, "atp_sresp: %m" );
507 * We assume buf is big enough for 255 bytes of data and a length byte.
510 int getstatus( pr, buf )
514 char path[ MAXPATHLEN ];
517 if ( pr->p_flags & P_SPOOLED && ( pr->p_spool != NULL )) {
518 strcpy( path, pr->p_spool );
519 strcat( path, "/status" );
520 fd = open( path, O_RDONLY);
523 if (( pr->p_flags & P_PIPED ) || ( fd < 0 )) {
524 *buf = strlen( cannedstatus );
525 strncpy( &buf[ 1 ], cannedstatus, *buf );
528 if (( rc = read( fd, &buf[ 1 ], 255 )) < 0 ) {
532 if ( rc && buf[ rc ] == '\n' ) { /* remove trailing newline */
541 char *getpname(char **area, int bufsize);
543 #define PF_CONFBUFFER 1024
545 static void getprinters( cf )
548 char buf[ PF_CONFBUFFER ], area[ PF_CONFBUFFER ], *a, *p, *name, *type, *zone;
552 while (( c = getprent( cf, buf, PF_CONFBUFFER )) > 0 ) {
555 * Get the printer's nbp name.
557 if (( p = getpname( &a, PF_CONFBUFFER )) == NULL ) {
558 fprintf( stderr, "No printer name\n" );
562 if (( pr = (struct printer *)malloc( sizeof( struct printer )))
567 memset( pr, 0, sizeof( struct printer ));
569 name = defprinter.p_name;
570 type = defprinter.p_type;
571 zone = defprinter.p_zone;
572 if ( nbp_name( p, &name, &type, &zone )) {
573 fprintf( stderr, "Can't parse \"%s\"\n", name );
576 if ( name != defprinter.p_name ) {
577 if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) {
581 strcpy( pr->p_name, name );
585 if ( type != defprinter.p_type ) {
586 if (( pr->p_type = (char *)malloc( strlen( type ) + 1 )) == NULL ) {
590 strcpy( pr->p_type, type );
594 if ( zone != defprinter.p_zone ) {
595 if (( pr->p_zone = (char *)malloc( strlen( zone ) + 1 )) == NULL ) {
599 strcpy( pr->p_zone, zone );
604 if ( pnchktc( cf ) != 1 ) {
605 fprintf( stderr, "Bad papcap entry\n" );
612 if (( p = pgetstr( "pd", &a )) == NULL ) {
613 pr->p_ppdfile = defprinter.p_ppdfile;
615 if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
619 strcpy( pr->p_ppdfile, p );
623 * Get lpd printer name.
625 if (( p = pgetstr( "pr", &a )) == NULL ) {
626 pr->p_printer = defprinter.p_printer;
627 pr->p_flags = defprinter.p_flags;
631 pr->p_flags = P_PIPED;
633 pr->p_flags = P_SPOOLED;
635 if (( pr->p_printer = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
639 strcpy( pr->p_printer, p );
643 * Do we want authenticated printing?
645 if ((p = pgetstr( "ca", &a )) != NULL ) {
646 if ((pr->p_authprintdir = (char *)malloc(strlen(p)+1)) == NULL) {
650 strcpy( pr->p_authprintdir, p );
651 pr->p_flags |= P_AUTH;
652 pr->p_flags |= P_AUTH_CAP;
653 } else { pr->p_authprintdir = NULL; }
655 if ( pgetflag( "sp" ) == 1 ) {
656 pr->p_flags |= P_AUTH;
657 pr->p_flags |= P_AUTH_PSSP;
660 if ((p = pgetstr("am", &a)) != NULL ) {
661 if ((uamlist = (char *)malloc(strlen(p)+1)) == NULL ) {
668 if ( pr->p_flags & P_SPOOLED ) {
672 if (( p = pgetstr( "op", &a )) == NULL ) {
673 pr->p_operator = defprinter.p_operator;
675 if (( pr->p_operator = (char *)malloc( strlen( p ) + 1 ))
680 strcpy( pr->p_operator, p );
684 /* get printer's appletalk address. */
685 if (( p = pgetstr( "pa", &a )) == NULL )
686 memcpy(&pr->p_addr, &defprinter.p_addr, sizeof(pr->p_addr));
688 atalk_aton(p, &pr->p_addr);
690 pr->p_next = printers;
695 } else { /* No capability file, do default */
696 printers = &defprinter;
703 char buf[ 1024 ], area[ 1024 ], *a, *p;
707 * Spool directory from printcap file.
709 if ( pr->p_flags & P_SPOOLED ) {
710 if ( pgetent( printcap, buf, pr->p_printer ) != 1 ) {
711 LOG(log_error, logtype_papd, "No such printer: %s", pr->p_printer );
718 if ( pr->p_spool != NULL && pr->p_spool != defprinter.p_spool ) {
722 if (( p = pgetstr( "sd", &a )) == NULL ) {
723 pr->p_spool = defprinter.p_spool;
725 if (( pr->p_spool = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
726 LOG(log_error, logtype_papd, "malloc: %m" );
729 strcpy( pr->p_spool, p );
736 if ( pgetstr( "af", &a ) == NULL ) {
737 pr->p_flags &= ~P_ACCOUNT;
739 pr->p_flags |= P_ACCOUNT;
741 if ( pr->p_role != NULL && pr->p_role != defprinter.p_role ) {
745 if (( p = pgetstr( "ro", &a )) == NULL ) {
746 pr->p_role = defprinter.p_role;
749 (char *)malloc( strlen( p ) + 1 )) == NULL ) {
750 LOG(log_error, logtype_papd, "malloc: %m" );
753 strcpy( pr->p_role, p );
756 if (( c = pgetnum( "si" )) < 0 ) {
757 pr->p_srvid = defprinter.p_srvid;
761 #endif /* ABS_PRINT */
768 if ( pr->p_pagecost_msg != NULL &&
769 pr->p_pagecost_msg != defprinter.p_pagecost_msg ) {
770 free( pr->p_pagecost_msg );
773 if (( p = pgetstr( "pc", &a )) != NULL ) {
774 if (( pr->p_pagecost_msg =
775 (char *)malloc( strlen( p ) + 1 )) == NULL ) {
776 LOG(log_error, logtype_papd, "malloc: %m" );
779 strcpy( pr->p_pagecost_msg, p );
781 } else if ( pr->p_flags & P_ACCOUNT ) {
782 if (( c = pgetnum( "pc" )) < 0 ) {
783 pr->p_pagecost = defprinter.p_pagecost;
787 pr->p_pagecost_msg = NULL;
793 if ( pr->p_lock != NULL && pr->p_lock != defprinter.p_lock ) {
797 if (( p = pgetstr( "lo", &a )) == NULL ) {
798 pr->p_lock = defprinter.p_lock;
800 if (( pr->p_lock = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
801 LOG(log_error, logtype_papd, "malloc: %m" );
804 strcpy( pr->p_lock, p );
809 * Must Kerberos authenticate?
811 if ( pgetflag( "ka" ) == 1 ) {
812 pr->p_flags |= P_KRB;
814 pr->p_flags &= ~P_KRB;