1/* 2 * $Id: main.c,v 1.31 2009-10-29 13:38:15 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 */ 43char *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 76#define PIPED_STATUS "status: print spooler processing job" 77 78struct printer defprinter; 79struct printer *printers = NULL; 80 81int debug = 0; 82static char *conffile = _PATH_PAPDCONF; 83char *printcap = _PATH_PAPDPRINTCAP; 84unsigned char connid, quantum, sock, oquantum = PAP_MAXQUANTUM; 85char *cannedstatus = PIPED_STATUS; 86struct printer *printer = NULL; 87char *version = VERSION; 88static char *pidfile = _PATH_PAPDLOCK; 89 90char *uamlist; 91char *uampath = _PATH_PAPDUAMPATH; 92 93/* Prototypes for locally used functions */ 94int getstatus( struct printer *pr, char *buf ); 95int rprintcap( struct printer *pr ); 96static void getprinters( char *cf ); 97 98 99/* this only needs to be used by the server process */ 100static void papd_exit(const int i) 101{ 102 server_unlock(pidfile); 103 auth_unload(); 104 exit(i); 105} 106 107static void 108die(int n) 109{ 110 struct printer *pr; 111 struct at_addr addr; 112 113 memset(&addr, 0, sizeof(addr)); 114 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 ); 120 papd_exit( n + 1 ); 121 } 122 LOG(log_info, logtype_papd, "unregister %s:%s@%s", pr->p_name, pr->p_type, 123 pr->p_zone ); 124 } 125#ifdef HAVE_CUPS 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); 129 } 130#endif /* HAVE_CUPS */ 131 132 } 133 papd_exit( n ); 134} 135 136static void 137reap(int sig _U_) 138{ 139 int status; 140 int pid; 141 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 )); 147 } else { 148 LOG(log_info, logtype_papd, "child %d done", pid ); 149 } 150 } else { 151 if ( WIFSIGNALED( status )) { 152 LOG(log_error, logtype_papd, "child %d killed with %d", pid, 153 WTERMSIG( status )); 154 } else { 155 LOG(log_error, logtype_papd, "child %d died", pid ); 156 } 157 } 158 } 159 return; 160} 161 162static char rbuf[ 255 + 1 + 8 ]; 163 164int main(int ac, char **av) 165{ 166 extern char *optarg; 167 168 ATP atp; 169 struct atp_block atpb; 170 struct sockaddr_at sat; 171 struct sigaction sv; 172 struct iovec iov; 173 fd_set fdset; 174 struct printer *pr; 175 char *p, hostname[ MAXHOSTNAMELEN ]; 176 char cbuf[ 8 ]; 177 int c; 178 char *atname; 179 180 if ( gethostname( hostname, sizeof( hostname )) < 0 ) { 181 perror( "gethostname" ); 182 exit( 1 ); 183 } 184 if (( p = strchr( hostname, '.' )) != NULL ) { 185 *p = '\0'; 186 } 187 if (( defprinter.p_name = (char *)malloc( strlen( hostname ) + 1 )) 188 == NULL ) { 189 perror( "malloc" ); 190 exit( 1 ); 191 } 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#ifdef __svr4__ 197 defprinter.p_flags = P_PIPED; 198 defprinter.p_printer = "/usr/bin/lp -T PS"; 199#else /* __svr4__ */ 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; 205#ifdef ABS_PRINT 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"; 212 213 while (( c = getopt( ac, av, "adf:p:P:v" )) != EOF ) { 214 switch ( c ) { 215 case 'a' : /* for compatibility with old papd */ 216 break; 217 218 case 'd' : /* debug */ 219 debug++; 220 break; 221 222 case 'f' : /* conffile */ 223 conffile = optarg; 224 break; 225 226 case 'p' : /* printcap */ 227 printcap = optarg; 228 break; 229 230 case 'P' : 231 pidfile = optarg; 232 break; 233 234 case 'v' : /* version */ 235 printf( "papd (version %s)\n", VERSION ); 236 exit ( 1 ); 237 break; 238 239 default : 240 fprintf( stderr, 241 "Usage:\t%s [ -d ] [ -f conffile ] [ -p printcap ]\n", 242 *av ); 243 exit( 1 ); 244 } 245 } 246 247 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) { 251 dup2(c, 1); 252 dup2(c, 2); 253 } 254 break; 255 case -1: 256 exit(1); 257 default: 258 exit(0); 259 } 260 261#ifdef DEBUG1 262 fault_setup(NULL); 263#endif 264 265 /* 266 * Start logging. 267 */ 268 if (( p = strrchr( av[ 0 ], '/' )) == NULL ) { 269 p = av[ 0 ]; 270 } else { 271 p++; 272 } 273#ifdef ultrix 274 openlog( p, LOG_PID ); 275#else /* ultrix */ 276 set_processname(p); 277 syslog_setup(log_debug, logtype_default, logoption_ndelay | logoption_pid | 278 debug ? logoption_perror : 0, logfacility_lpr ); 279#endif /* ultrix */ 280 281 LOG(log_info, logtype_papd, "restart (%s)", version ); 282#ifdef HAVE_CUPS 283 LOG(log_info, logtype_papd, "CUPS support enabled (%s)", CUPS_API_VERSION ); 284#endif 285 286 getprinters( conffile ); 287 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 ); 291 } 292 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; 296 pr->p_name = atname; 297 } 298 } 299 300 if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) { 301 LOG(log_error, logtype_papd, "atp_open: %s", strerror(errno) ); 302 papd_exit( 1 ); 303 } 304 if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type, 305 pr->p_zone ) < 0 ) { 306 LOG(log_error, logtype_papd, "can't register %s:%s@%s", pr->p_u_name, pr->p_type, 307 pr->p_zone ); 308 die( 1 ); 309 } 310 if ( pr->p_flags & P_AUTH ) { 311 LOG(log_info, logtype_papd, "Authentication enabled: %s", pr->p_u_name ); 312 } 313 else { 314 LOG(log_info, logtype_papd, "Authentication disabled: %s", pr->p_u_name ); 315 } 316 LOG(log_info, logtype_papd, "register %s:%s@%s", pr->p_u_name, pr->p_type, 317 pr->p_zone ); 318 pr->p_flags |= P_REGISTERED; 319 } 320 321 memset(&sv, 0, sizeof(sv)); 322 sv.sa_handler = die; 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) ); 327 papd_exit( 1 ); 328 } 329 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) ); 335 papd_exit( 1 ); 336 } 337 338 /* 339 * Load UAMS 340 */ 341 auth_load(uampath, uamlist); 342 343 /* 344 * Begin accepting connections. 345 */ 346 FD_ZERO( &fdset ); 347 for (;;) { 348 for ( pr = printers; pr; pr = pr->p_next ) { 349 FD_SET( atp_fileno( pr->p_atp ), &fdset ); 350 } 351 if (( c = select( FD_SETSIZE, &fdset, NULL, NULL, NULL )) < 0 ) { 352 if ( errno == EINTR ) { 353 continue; 354 } 355 LOG(log_error, logtype_papd, "select: %s", strerror(errno) ); 356 papd_exit( 1 ); 357 } 358 359 for ( pr = printers; pr; pr = pr->p_next ) { 360 if ( FD_ISSET( atp_fileno( pr->p_atp ), &fdset )) { 361 int err = 0; 362 363 memset( &sat, 0, sizeof( struct sockaddr_at )); 364#ifdef BSD4_4 365 sat.sat_len = sizeof( struct sockaddr_at ); 366#endif /* BSD4_4 */ 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 ) { 373 continue; 374 } 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) ); 380 continue; 381 } 382 383 /* should check length of req buf */ 384 385 switch( cbuf[ 1 ] ) { 386 case PAP_OPEN : 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; 393 394 if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) != 0 ) { 395 LOG(log_error, logtype_papd, "printcap problem: %s", 396 pr->p_printer ); 397 rbuf[ 2 ] = rbuf[ 3 ] = 0xff; 398 err = 1; 399 } 400 401#ifdef HAVE_CUPS 402 /* 403 * If cups is not accepting jobs, we return 404 * 0xffff to indicate we're busy 405 */ 406#ifdef DEBUG 407 LOG(log_debug9, logtype_papd, "CUPS: PAP_OPEN"); 408#endif 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", 411 pr->p_printer ); 412 rbuf[ 2 ] = rbuf[ 3 ] = 0xff; 413 err = 1; 414 } 415#endif /* HAVE_CUPS */ 416 417 /* 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; 421 */ 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? */ 427 err = 1; 428 } 429 else { 430 rbuf[ 4 ] = atp_sockaddr( atp )->sat_port; 431 } 432 rbuf[ 5 ] = oquantum; 433 rbuf[ 6 ] = rbuf[ 7 ] = 0; 434 435 iov.iov_base = rbuf; 436 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] ); 437 atpb.atp_sresiov = &iov; 438 atpb.atp_sresiovcnt = 1; 439 /* 440 * This may error out if we lose a route, so we won't die(). 441 */ 442 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) { 443 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) ); 444 err = 1; 445 } 446 447 if ( err ) { 448 if (atp) { 449 atp_close(atp); 450 } 451 continue; 452 } 453 454 switch ( c = fork()) { 455 case -1 : 456 LOG(log_error, logtype_papd, "fork: %s", strerror(errno) ); 457 atp_close(atp); 458 continue; 459 460 case 0 : /* child */ 461 printer = pr; 462 463 #ifndef HAVE_CUPS 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) ); 467 exit( 1 ); 468 } 469 #else 470 if (( printer->p_flags & P_SPOOLED ) && 471 chdir( SPOOLDIR ) < 0 ) { 472 LOG(log_error, logtype_papd, "chdir %s: %s", SPOOLDIR, strerror(errno) ); 473 exit( 1 ); 474 } 475 476 #endif 477 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) ); 483 exit( 1 ); 484 } 485 486 if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) { 487 LOG(log_error, logtype_papd, "sigaction: %s", strerror(errno) ); 488 exit( 1 ); 489 } 490 491 for ( pr = printers; pr; pr = pr->p_next ) { 492 atp_close( pr->p_atp ); 493 } 494 sat.sat_port = sock; 495 if ( session( atp, &sat ) < 0 ) { 496 LOG(log_error, logtype_papd, "bad session" ); 497 exit( 1 ); 498 } 499 exit( 0 ); 500 break; 501 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); 506 atp_close( atp ); 507 } 508 break; 509 510 case PAP_SENDSTATUS : 511 rbuf[ 0 ] = 0; 512 rbuf[ 1 ] = PAP_STATUS; 513 rbuf[ 2 ] = rbuf[ 3 ] = 0; 514 rbuf[ 4 ] = rbuf[ 5 ] = 0; 515 rbuf[ 6 ] = rbuf[ 7 ] = 0; 516 517 iov.iov_base = rbuf; 518 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] ); 519 atpb.atp_sresiov = &iov; 520 atpb.atp_sresiovcnt = 1; 521 /* 522 * This may error out if we lose a route, so we won't die(). 523 */ 524 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) { 525 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) ); 526 } 527 break; 528 529 default : 530 LOG(log_error, logtype_papd, "Bad request from %u.%u!", 531 ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node ); 532 continue; 533 break; 534 } 535 536#ifdef notdef 537 /* 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. 541 */ 542 iov.iov_base = rbuf; 543 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] ); 544 atpb.atp_sresiov = &iov; 545 atpb.atp_sresiovcnt = 1; 546 /* 547 * This may error out if we lose a route, so we won't die(). 548 */ 549 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) { 550 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) ); 551 } 552#endif /* notdef */ 553 } 554 } 555 } 556 return 0; 557} 558 559/* 560 * We assume buf is big enough for 255 bytes of data and a length byte. 561 */ 562 563int getstatus(struct printer *pr, char *buf) 564{ 565 566#ifdef HAVE_CUPS 567 if ( pr->p_flags & P_PIPED ) { 568 *buf = strlen( cannedstatus ); 569 strncpy( &buf[ 1 ], cannedstatus, *buf ); 570 return( *buf + 1 ); 571 } else { 572 cups_get_printer_status( pr ); 573 *buf = strlen ( pr->p_status ); 574 strncpy ( &buf[1], pr->p_status, *buf); 575 return ( *buf + 1); 576 } 577#else 578 579 char path[ MAXPATHLEN ]; 580 int fd = -1, rc; 581 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); 586 } 587 588 if (( pr->p_flags & P_PIPED ) || ( fd < 0 )) { 589 *buf = strlen( cannedstatus ); 590 strncpy( &buf[ 1 ], cannedstatus, *buf ); 591 return( *buf + 1 ); 592 } else { 593 if (( rc = read( fd, &buf[ 1 ], 255 )) < 0 ) { 594 rc = 0; 595 } 596 close( fd ); 597 if ( rc && buf[ rc ] == '\n' ) { /* remove trailing newline */ 598 rc--; 599 } 600 *buf = rc; 601 return( rc + 1 ); 602 } 603#endif /* HAVE_CUPS */ 604} 605 606char *pgetstr(char *id, char **area); 607char *getpname(char **area, int bufsize); 608 609#define PF_CONFBUFFER 1024 610 611static void getprinters( char *cf) 612{ 613 char buf[ PF_CONFBUFFER ], area[ PF_CONFBUFFER ], *a, *p, *name, *type, *zone; 614 struct printer *pr; 615 int c; 616 617 while (( c = getprent( cf, buf, PF_CONFBUFFER )) > 0 ) { 618 a = area; 619 /* 620 * Get the printer's nbp name. 621 */ 622 if (( p = getpname( &a, PF_CONFBUFFER )) == NULL ) { 623 fprintf( stderr, "No printer name\n" ); 624 exit( 1 ); 625 } 626 627 if (( pr = (struct printer *)malloc( sizeof( struct printer ))) 628 == NULL ) { 629 perror( "malloc" ); 630 exit( 1 ); 631 } 632 memset( pr, 0, sizeof( struct printer )); 633 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 ); 639 exit( 1 ); 640 } 641 if ( name != defprinter.p_name ) { 642 if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) { 643 perror( "malloc" ); 644 exit( 1 ); 645 } 646 strcpy( pr->p_name, name ); 647 } else { 648 pr->p_name = name; 649 } 650 if ( type != defprinter.p_type ) { 651 if (( pr->p_type = (char *)malloc( strlen( type ) + 1 )) == NULL ) { 652 perror( "malloc" ); 653 exit( 1 ); 654 } 655 strcpy( pr->p_type, type ); 656 } else { 657 pr->p_type = type; 658 } 659 if ( zone != defprinter.p_zone ) { 660 if (( pr->p_zone = (char *)malloc( strlen( zone ) + 1 )) == NULL ) { 661 perror( "malloc" ); 662 exit( 1 ); 663 } 664 strcpy( pr->p_zone, zone ); 665 } else { 666 pr->p_zone = zone; 667 } 668 669 if ( pnchktc( cf ) != 1 ) { 670 fprintf( stderr, "Bad papcap entry\n" ); 671 exit( 1 ); 672 } 673 674 /* 675 * Get PPD file. 676 */ 677 if (( p = pgetstr( "pd", &a ) )) { 678 if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) { 679 perror( "malloc" ); 680 exit( 1 ); 681 } 682 strcpy( pr->p_ppdfile, p ); 683 } 684 685 /* 686 * Get lpd printer name. 687 */ 688 if (( p = pgetstr( "pr", &a )) == NULL ) { 689 pr->p_printer = defprinter.p_printer; 690 pr->p_flags = defprinter.p_flags; 691 } else { 692 if ( *p == '|' ) { 693 p++; 694 pr->p_flags = P_PIPED; 695 } else { 696 pr->p_flags = P_SPOOLED; 697 } 698 if (( pr->p_printer = (char *)malloc( strlen( p ) + 1 )) == NULL ) { 699 perror( "malloc" ); 700 exit( 1 ); 701 } 702 strcpy( pr->p_printer, p ); 703 } 704 705 /* 706 * Do we want authenticated printing? 707 */ 708 if ((p = pgetstr( "ca", &a )) != NULL ) { 709 if ((pr->p_authprintdir = (char *)malloc(strlen(p)+1)) == NULL) { 710 perror( "malloc" ); 711 exit(1); 712 } 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; } 717 718 if ( pgetflag( "sp" ) == 1 ) { 719 pr->p_flags |= P_AUTH; 720 pr->p_flags |= P_AUTH_PSSP; 721 } 722 723 if ((p = pgetstr("am", &a)) != NULL ) { 724 if ((uamlist = (char *)malloc(strlen(p)+1)) == NULL ) { 725 perror("malloc"); 726 exit(1); 727 } 728 strcpy(uamlist, p); 729 } 730 731 if ( pr->p_flags & P_SPOOLED ) { 732 /* 733 * Get operator name. 734 */ 735 if (( p = pgetstr( "op", &a )) == NULL ) { 736 pr->p_operator = defprinter.p_operator; 737 } else { 738 if (( pr->p_operator = (char *)malloc( strlen( p ) + 1 )) 739 == NULL ) { 740 perror( "malloc" ); 741 exit( 1 ); 742 } 743 strcpy( pr->p_operator, p ); 744 } 745 } 746 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)); 750 else 751 atalk_aton(p, &pr->p_addr); 752 753#ifdef HAVE_CUPS 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); 757 } 758#endif 759 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); 766 } 767 768 if (strncasecmp (pr->p_name, "cupsautoadd", 11) == 0) 769 { 770#ifdef HAVE_CUPS 771 pr = cups_autoadd_printers (pr, printers); 772 printers = pr; 773#else 774 LOG (log_error, logtype_papd, "cupsautoadd: Cups support not compiled in"); 775#endif /* HAVE_CUPS */ 776 } 777 else { 778#ifdef HAVE_CUPS 779 if ( cups_check_printer ( pr, printers, 1) == 0) 780 { 781 pr->p_next = printers; 782 printers = pr; 783 } 784#else 785 pr->p_next = printers; 786 printers = pr; 787#endif /* HAVE_CUPS */ 788 } 789 } 790 if ( c == 0 ) { 791 endprent(); 792 } else { /* No capability file, do default */ 793 printers = &defprinter; 794 } 795} 796 797int rprintcap( struct printer *pr) 798{ 799 800#ifdef HAVE_CUPS 801 802 char *p; 803 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 ); 807 return( -1 ); 808 } 809 } 810 811 /* 812 * Check for ppd file, moved here because of cups_autoadd we cannot check at the usual location 813 */ 814 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) ); 819 exit( 1 ); 820 } 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 ); 824 } 825 } 826 827 828#else 829 830 char buf[ 1024 ], area[ 1024 ], *a, *p; 831 int c; 832 833 /* 834 * Spool directory from printcap file. 835 */ 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 ); 839 return( -1 ); 840 } 841 842 /* 843 * Spool directory. 844 */ 845 if ( pr->p_spool != NULL && pr->p_spool != defprinter.p_spool ) { 846 free( pr->p_spool ); 847 } 848 a = area; 849 if (( p = pgetstr( "sd", &a )) == NULL ) { 850 pr->p_spool = defprinter.p_spool; 851 } else { 852 if (( pr->p_spool = (char *)malloc( strlen( p ) + 1 )) == NULL ) { 853 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) ); 854 exit( 1 ); 855 } 856 strcpy( pr->p_spool, p ); 857 } 858 859 /* 860 * Is accounting on? 861 */ 862 a = area; 863 if ( pgetstr( "af", &a ) == NULL ) { 864 pr->p_flags &= ~P_ACCOUNT; 865 } else { 866 pr->p_flags |= P_ACCOUNT; 867#ifdef ABS_PRINT 868 if ( pr->p_role != NULL && pr->p_role != defprinter.p_role ) { 869 free( pr->p_role ); 870 } 871 a = area; 872 if (( p = pgetstr( "ro", &a )) == NULL ) { 873 pr->p_role = defprinter.p_role; 874 } else { 875 if (( pr->p_role = 876 (char *)malloc( strlen( p ) + 1 )) == NULL ) { 877 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) ); 878 exit( 1 ); 879 } 880 strcpy( pr->p_role, p ); 881 } 882 883 if (( c = pgetnum( "si" )) < 0 ) { 884 pr->p_srvid = defprinter.p_srvid; 885 } else { 886 pr->p_srvid = c; 887 } 888#endif /* ABS_PRINT */ 889 } 890 891 892 /* 893 * Cost of printer. 894 */ 895 if ( pr->p_pagecost_msg != NULL && 896 pr->p_pagecost_msg != defprinter.p_pagecost_msg ) { 897 free( pr->p_pagecost_msg ); 898 } 899 a = area; 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) ); 904 exit( 1 ); 905 } 906 strcpy( pr->p_pagecost_msg, p ); 907 pr->p_pagecost = 0; 908 } else if ( pr->p_flags & P_ACCOUNT ) { 909 if (( c = pgetnum( "pc" )) < 0 ) { 910 pr->p_pagecost = defprinter.p_pagecost; 911 } else { 912 pr->p_pagecost = c; 913 } 914 pr->p_pagecost_msg = NULL; 915 } 916 917 /* 918 * Get lpd lock file. 919 */ 920 if ( pr->p_lock != NULL && pr->p_lock != defprinter.p_lock ) { 921 free( pr->p_lock ); 922 } 923 a = area; 924 if (( p = pgetstr( "lo", &a )) == NULL ) { 925 pr->p_lock = defprinter.p_lock; 926 } else { 927 if (( pr->p_lock = (char *)malloc( strlen( p ) + 1 )) == NULL ) { 928 LOG(log_error, logtype_papd, "malloc: %s", strerror(errno) ); 929 exit( 1 ); 930 } 931 strcpy( pr->p_lock, p ); 932 } 933 934#ifdef KRB 935 /* 936 * Must Kerberos authenticate? 937 */ 938 if ( pgetflag( "ka" ) == 1 ) { 939 pr->p_flags |= P_KRB; 940 } else { 941 pr->p_flags &= ~P_KRB; 942 } 943#endif /* KRB */ 944 945 endprent(); 946 } 947#endif /* HAVE_CUPS */ 948 949 return( 0 ); 950} 951