2 * $Id: main.c,v 1.31 2009-10-29 13:38:15 didg Exp $
4 * Copyright (c) 1990,1995 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
14 #include <sys/param.h>
18 #include <sys/socket.h>
19 #include <atalk/logger.h>
21 /* POSIX.1 sys/wait.h check */
22 #include <sys/types.h>
23 #ifdef HAVE_SYS_WAIT_H
25 #endif /* HAVE_SYS_WAIT_H */
27 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
28 #endif /* ! WEXITSTATUS */
30 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
31 #endif /* ! WIFEXITED */
38 #else /* STDC_HEADERS */
42 #endif /* HAVE_STRCHR */
43 char *strchr (), *strrchr ();
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 */
57 #endif /* HAVE_UNISTD_H */
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>
73 #include "print_cups.h"
76 #define PIPED_STATUS "status: print spooler processing job"
78 struct printer defprinter;
79 struct printer *printers = NULL;
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;
91 char *uampath = _PATH_PAPDUAMPATH;
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 );
99 /* this only needs to be used by the server process */
100 static void papd_exit(const int i)
102 server_unlock(pidfile);
113 memset(&addr, 0, sizeof(addr));
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 );
122 LOG(log_info, logtype_papd, "unregister %s:%s@%s", pr->p_name, pr->p_type,
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);
130 #endif /* HAVE_CUPS */
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 ));
148 LOG(log_info, logtype_papd, "child %d done", pid );
151 if ( WIFSIGNALED( status )) {
152 LOG(log_error, logtype_papd, "child %d killed with %d", pid,
155 LOG(log_error, logtype_papd, "child %d died", pid );
162 static char rbuf[ 255 + 1 + 8 ];
164 int main(int ac, char **av)
169 struct atp_block atpb;
170 struct sockaddr_at sat;
175 char *p, hostname[ MAXHOSTNAMELEN ];
180 if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
181 perror( "gethostname" );
184 if (( p = strchr( hostname, '.' )) != NULL ) {
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));
197 defprinter.p_flags = P_PIPED;
198 defprinter.p_printer = "/usr/bin/lp -T PS";
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;
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";
213 while (( c = getopt( ac, av, "adf:p:P:v" )) != EOF ) {
215 case 'a' : /* for compatibility with old papd */
218 case 'd' : /* debug */
222 case 'f' : /* conffile */
226 case 'p' : /* printcap */
234 case 'v' : /* version */
235 printf( "papd (version %s)\n", VERSION );
241 "Usage:\t%s [ -d ] [ -f conffile ] [ -p printcap ]\n",
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) {
268 if (( p = strrchr( av[ 0 ], '/' )) == NULL ) {
274 openlog( p, LOG_PID );
277 syslog_setup(log_debug, logtype_default, logoption_ndelay | logoption_pid |
278 debug ? logoption_perror : 0, logfacility_lpr );
281 LOG(log_info, logtype_papd, "restart (%s)", version );
283 LOG(log_info, logtype_papd, "CUPS support enabled (%s)", CUPS_API_VERSION );
286 getprinters( conffile );
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 );
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;
300 if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) {
301 LOG(log_error, logtype_papd, "atp_open: %s", strerror(errno) );
304 if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type,
306 LOG(log_error, logtype_papd, "can't register %s:%s@%s", pr->p_u_name, pr->p_type,
310 if ( pr->p_flags & P_AUTH ) {
311 LOG(log_info, logtype_papd, "Authentication enabled: %s", pr->p_u_name );
314 LOG(log_info, logtype_papd, "Authentication disabled: %s", pr->p_u_name );
316 LOG(log_info, logtype_papd, "register %s:%s@%s", pr->p_u_name, pr->p_type,
318 pr->p_flags |= P_REGISTERED;
321 memset(&sv, 0, sizeof(sv));
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) );
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) );
341 auth_load(uampath, uamlist);
344 * Begin accepting connections.
348 for ( pr = printers; pr; pr = pr->p_next ) {
349 FD_SET( atp_fileno( pr->p_atp ), &fdset );
351 if (( c = select( FD_SETSIZE, &fdset, NULL, NULL, NULL )) < 0 ) {
352 if ( errno == EINTR ) {
355 LOG(log_error, logtype_papd, "select: %s", strerror(errno) );
359 for ( pr = printers; pr; pr = pr->p_next ) {
360 if ( FD_ISSET( atp_fileno( pr->p_atp ), &fdset )) {
363 memset( &sat, 0, sizeof( struct sockaddr_at ));
365 sat.sat_len = sizeof( struct sockaddr_at );
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 ) {
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) );
383 /* should check length of req buf */
385 switch( cbuf[ 1 ] ) {
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;
394 if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) != 0 ) {
395 LOG(log_error, logtype_papd, "printcap problem: %s",
397 rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
403 * If cups is not accepting jobs, we return
404 * 0xffff to indicate we're busy
407 LOG(log_debug9, logtype_papd, "CUPS: PAP_OPEN");
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",
412 rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
415 #endif /* HAVE_CUPS */
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;
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? */
430 rbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
432 rbuf[ 5 ] = oquantum;
433 rbuf[ 6 ] = rbuf[ 7 ] = 0;
436 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
437 atpb.atp_sresiov = &iov;
438 atpb.atp_sresiovcnt = 1;
440 * This may error out if we lose a route, so we won't die().
442 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
443 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );
454 switch ( c = fork()) {
456 LOG(log_error, logtype_papd, "fork: %s", strerror(errno) );
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) );
470 if (( printer->p_flags & P_SPOOLED ) &&
471 chdir( SPOOLDIR ) < 0 ) {
472 LOG(log_error, logtype_papd, "chdir %s: %s", SPOOLDIR, strerror(errno) );
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) );
486 if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) {
487 LOG(log_error, logtype_papd, "sigaction: %s", strerror(errno) );
491 for ( pr = printers; pr; pr = pr->p_next ) {
492 atp_close( pr->p_atp );
495 if ( session( atp, &sat ) < 0 ) {
496 LOG(log_error, logtype_papd, "bad session" );
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);
510 case PAP_SENDSTATUS :
512 rbuf[ 1 ] = PAP_STATUS;
513 rbuf[ 2 ] = rbuf[ 3 ] = 0;
514 rbuf[ 4 ] = rbuf[ 5 ] = 0;
515 rbuf[ 6 ] = rbuf[ 7 ] = 0;
518 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
519 atpb.atp_sresiov = &iov;
520 atpb.atp_sresiovcnt = 1;
522 * This may error out if we lose a route, so we won't die().
524 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
525 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );
530 LOG(log_error, logtype_papd, "Bad request from %u.%u!",
531 ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node );
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.
543 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
544 atpb.atp_sresiov = &iov;
545 atpb.atp_sresiovcnt = 1;
547 * This may error out if we lose a route, so we won't die().
549 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
550 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );
560 * We assume buf is big enough for 255 bytes of data and a length byte.
563 int getstatus(struct printer *pr, char *buf)
567 if ( pr->p_flags & P_PIPED ) {
568 *buf = strlen( cannedstatus );
569 strncpy( &buf[ 1 ], cannedstatus, *buf );
572 cups_get_printer_status( pr );
573 *buf = strlen ( pr->p_status );
574 strncpy ( &buf[1], pr->p_status, *buf);
579 char path[ MAXPATHLEN ];
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);
588 if (( pr->p_flags & P_PIPED ) || ( fd < 0 )) {
589 *buf = strlen( cannedstatus );
590 strncpy( &buf[ 1 ], cannedstatus, *buf );
593 if (( rc = read( fd, &buf[ 1 ], 255 )) < 0 ) {
597 if ( rc && buf[ rc ] == '\n' ) { /* remove trailing newline */
603 #endif /* HAVE_CUPS */
606 char *pgetstr(char *id, char **area);
607 char *getpname(char **area, int bufsize);
609 #define PF_CONFBUFFER 1024
611 static void getprinters( char *cf)
613 char buf[ PF_CONFBUFFER ], area[ PF_CONFBUFFER ], *a, *p, *name, *type, *zone;
617 while (( c = getprent( cf, buf, PF_CONFBUFFER )) > 0 ) {
620 * Get the printer's nbp name.
622 if (( p = getpname( &a, PF_CONFBUFFER )) == NULL ) {
623 fprintf( stderr, "No printer name\n" );
627 if (( pr = (struct printer *)malloc( sizeof( struct printer )))
632 memset( pr, 0, sizeof( struct printer ));
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 );
641 if ( name != defprinter.p_name ) {
642 if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) {
646 strcpy( pr->p_name, name );
650 if ( type != defprinter.p_type ) {
651 if (( pr->p_type = (char *)malloc( strlen( type ) + 1 )) == NULL ) {
655 strcpy( pr->p_type, type );
659 if ( zone != defprinter.p_zone ) {
660 if (( pr->p_zone = (char *)malloc( strlen( zone ) + 1 )) == NULL ) {
664 strcpy( pr->p_zone, zone );
669 if ( pnchktc( cf ) != 1 ) {
670 fprintf( stderr, "Bad papcap entry\n" );
677 if (( p = pgetstr( "pd", &a ) )) {
678 if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
682 strcpy( pr->p_ppdfile, p );
686 * Get lpd printer name.
688 if (( p = pgetstr( "pr", &a )) == NULL ) {
689 pr->p_printer = defprinter.p_printer;
690 pr->p_flags = defprinter.p_flags;
694 pr->p_flags = P_PIPED;
696 pr->p_flags = P_SPOOLED;
698 if (( pr->p_printer = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
702 strcpy( pr->p_printer, p );
706 * Do we want authenticated printing?
708 if ((p = pgetstr( "ca", &a )) != NULL ) {
709 if ((pr->p_authprintdir = (char *)malloc(strlen(p)+1)) == NULL) {
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; }
718 if ( pgetflag( "sp" ) == 1 ) {
719 pr->p_flags |= P_AUTH;
720 pr->p_flags |= P_AUTH_PSSP;
723 if ((p = pgetstr("am", &a)) != NULL ) {
724 if ((uamlist = (char *)malloc(strlen(p)+1)) == NULL ) {
731 if ( pr->p_flags & P_SPOOLED ) {
735 if (( p = pgetstr( "op", &a )) == NULL ) {
736 pr->p_operator = defprinter.p_operator;
738 if (( pr->p_operator = (char *)malloc( strlen( p ) + 1 ))
743 strcpy( pr->p_operator, p );
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));
751 atalk_aton(p, &pr->p_addr);
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);
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);
768 if (strncasecmp (pr->p_name, "cupsautoadd", 11) == 0)
771 pr = cups_autoadd_printers (pr, printers);
774 LOG (log_error, logtype_papd, "cupsautoadd: Cups support not compiled in");
775 #endif /* HAVE_CUPS */
779 if ( cups_check_printer ( pr, printers, 1) == 0)
781 pr->p_next = printers;
785 pr->p_next = printers;
787 #endif /* HAVE_CUPS */
792 } else { /* No capability file, do default */
793 printers = &defprinter;
797 int rprintcap( struct printer *pr)
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 );
812 * Check for ppd file, moved here because of cups_autoadd we cannot check at the usual location
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) );
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 );
830 char buf[ 1024 ], area[ 1024 ], *a, *p;
834 * Spool directory from printcap file.
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 );
845 if ( pr->p_spool != NULL && pr->p_spool != defprinter.p_spool ) {
849 if (( p = pgetstr( "sd", &a )) == NULL ) {
850 pr->p_spool = defprinter.p_spool;
852 if (( pr->p_spool = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
853 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
856 strcpy( pr->p_spool, p );
863 if ( pgetstr( "af", &a ) == NULL ) {
864 pr->p_flags &= ~P_ACCOUNT;
866 pr->p_flags |= P_ACCOUNT;
868 if ( pr->p_role != NULL && pr->p_role != defprinter.p_role ) {
872 if (( p = pgetstr( "ro", &a )) == NULL ) {
873 pr->p_role = defprinter.p_role;
876 (char *)malloc( strlen( p ) + 1 )) == NULL ) {
877 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
880 strcpy( pr->p_role, p );
883 if (( c = pgetnum( "si" )) < 0 ) {
884 pr->p_srvid = defprinter.p_srvid;
888 #endif /* ABS_PRINT */
895 if ( pr->p_pagecost_msg != NULL &&
896 pr->p_pagecost_msg != defprinter.p_pagecost_msg ) {
897 free( pr->p_pagecost_msg );
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) );
906 strcpy( pr->p_pagecost_msg, p );
908 } else if ( pr->p_flags & P_ACCOUNT ) {
909 if (( c = pgetnum( "pc" )) < 0 ) {
910 pr->p_pagecost = defprinter.p_pagecost;
914 pr->p_pagecost_msg = NULL;
920 if ( pr->p_lock != NULL && pr->p_lock != defprinter.p_lock ) {
924 if (( p = pgetstr( "lo", &a )) == NULL ) {
925 pr->p_lock = defprinter.p_lock;
927 if (( pr->p_lock = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
928 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) );
931 strcpy( pr->p_lock, p );
936 * Must Kerberos authenticate?
938 if ( pgetflag( "ka" ) == 1 ) {
939 pr->p_flags |= P_KRB;
941 pr->p_flags &= ~P_KRB;
947 #endif /* HAVE_CUPS */