This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "IPFire 3.x development tree".
The branch, master has been updated via d15dc44446babbc3cfc8ac70e3e5bd15771749fa (commit) via 5720224feef73a1ffe0e1b794e59a70324824921 (commit) via 9f2ffaaf647c550c928bd2a7edf6b636e8136d00 (commit) via 7be6fddba61c8bd63457bfc6f32500b7f11b5fa8 (commit) via f92713d3842a76bb858f302ba749c296635b49d0 (commit) via 1d1a660359caea0edb6e6987178685cd92e8e2ed (commit) from 8e872b12350c40e834c1b65a506eacc5aad0d920 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit d15dc44446babbc3cfc8ac70e3e5bd15771749fa Merge: 5720224 9f2ffaa Author: Michael Tremer michael.tremer@ipfire.org Date: Sun Jan 2 17:12:40 2011 +0100
Merge remote branch 'stevee/libnih'
commit 5720224feef73a1ffe0e1b794e59a70324824921 Author: Michael Tremer michael.tremer@ipfire.org Date: Sun Jan 2 17:12:13 2011 +0100
cups: Build fix.
libgcrypt headers were required to build.
commit 9f2ffaaf647c550c928bd2a7edf6b636e8136d00 Author: Stefan Schantl stefan.schantl@ipfire.org Date: Sat Jan 1 15:58:35 2011 +0100
libnih: Update to 1.0.3.
commit 7be6fddba61c8bd63457bfc6f32500b7f11b5fa8 Author: Stefan Schantl stefan.schantl@ipfire.org Date: Thu Dec 30 14:16:39 2010 +0100
cups: Add file for logrotate.
commit f92713d3842a76bb858f302ba749c296635b49d0 Author: Stefan Schantl stefan.schantl@ipfire.org Date: Thu Dec 30 14:10:03 2010 +0100
cups: Add a lot of patches.
* Lot of bug fixes. * Provides support for selinux. * Provides support for audit. * Support for avahi. * Support for gnutls.
commit 1d1a660359caea0edb6e6987178685cd92e8e2ed Author: Stefan Schantl stefan.schantl@ipfire.org Date: Thu Dec 30 12:27:36 2010 +0100
coreutils: Enable support for selinux.
-----------------------------------------------------------------------
Summary of changes: pkgs/core/coreutils/coreutils.nm | 5 +- .../core/coreutils/patches/coreutils-selinux.patch | 671 ++++ .../patches/coreutils-selinuxmanpages.patch | 15 + pkgs/core/cups/cups.logrotate | 5 + pkgs/core/cups/cups.nm | 26 +- pkgs/core/cups/patches/cups-0755.patch | 32 + .../cups/patches/cups-1.1.16-system-auth.patch | 39 + pkgs/core/cups/patches/cups-EAI_AGAIN.patch | 12 + pkgs/core/cups/patches/cups-autotype-crash.patch | 15 + pkgs/core/cups/patches/cups-avahi.patch | 3338 ++++++++++++++++++++ pkgs/core/cups/patches/cups-banners.patch | 11 + pkgs/core/cups/patches/cups-build.patch | 42 + pkgs/core/cups/patches/cups-cups-get-classes.patch | 90 + pkgs/core/cups/patches/cups-direct-usb.patch | 27 + pkgs/core/cups/patches/cups-dnssd-deviceid.patch | 38 + pkgs/core/cups/patches/cups-driverd-timeout.patch | 21 + pkgs/core/cups/patches/cups-eggcups.patch | 130 + pkgs/core/cups/patches/cups-filter-debug.patch | 32 + pkgs/core/cups/patches/cups-force-gnutls.patch | 89 + pkgs/core/cups/patches/cups-getpass.patch | 43 + pkgs/core/cups/patches/cups-hostnamelookups.patch | 24 + pkgs/core/cups/patches/cups-hp-deviceid-oid.patch | 21 + pkgs/core/cups/patches/cups-logrotate.patch | 63 + pkgs/core/cups/patches/cups-lpr-help.patch | 56 + pkgs/core/cups/patches/cups-multilib.patch | 15 + .../core/cups/patches/cups-no-export-ssllibs.patch | 12 + pkgs/core/cups/patches/cups-no-gzip-man.patch | 18 + pkgs/core/cups/patches/cups-page-label.patch | 92 + pkgs/core/cups/patches/cups-peercred.patch | 11 + pkgs/core/cups/patches/cups-pid.patch | 36 + pkgs/core/cups/patches/cups-res_init.patch | 12 + .../cups/patches/cups-ricoh-deviceid-oid.patch | 21 + pkgs/core/cups/patches/cups-serial.patch | 11 + pkgs/core/cups/patches/cups-serialize-gnutls.patch | 109 + pkgs/core/cups/patches/cups-serverbin-compat.patch | 194 ++ pkgs/core/cups/patches/cups-snmp-quirks.patch | 115 + pkgs/core/cups/patches/cups-str3382.patch | 64 + pkgs/core/cups/patches/cups-str3754.patch | 11 + .../cups/patches/cups-strict-ppd-line-length.patch | 30 + .../cups/patches/cups-texttops-rotate-page.patch | 35 + pkgs/core/cups/patches/cups-uri-compat.patch | 51 + pkgs/core/cups/patches/cups-usb-paperout.patch | 52 + pkgs/core/cups/patches/cups-x-lspp.patch | 2839 +++++++++++++++++ pkgs/core/libnih/libnih.nm | 7 +- .../libnih/patches/libnih-1.0.2-upstream-1.patch | 246 -- 45 files changed, 8570 insertions(+), 256 deletions(-) create mode 100644 pkgs/core/coreutils/patches/coreutils-selinux.patch create mode 100644 pkgs/core/coreutils/patches/coreutils-selinuxmanpages.patch create mode 100644 pkgs/core/cups/cups.logrotate create mode 100644 pkgs/core/cups/patches/cups-0755.patch create mode 100644 pkgs/core/cups/patches/cups-1.1.16-system-auth.patch create mode 100644 pkgs/core/cups/patches/cups-EAI_AGAIN.patch create mode 100644 pkgs/core/cups/patches/cups-autotype-crash.patch create mode 100644 pkgs/core/cups/patches/cups-avahi.patch create mode 100644 pkgs/core/cups/patches/cups-banners.patch create mode 100644 pkgs/core/cups/patches/cups-build.patch create mode 100644 pkgs/core/cups/patches/cups-cups-get-classes.patch create mode 100644 pkgs/core/cups/patches/cups-direct-usb.patch create mode 100644 pkgs/core/cups/patches/cups-dnssd-deviceid.patch create mode 100644 pkgs/core/cups/patches/cups-driverd-timeout.patch create mode 100644 pkgs/core/cups/patches/cups-eggcups.patch create mode 100644 pkgs/core/cups/patches/cups-filter-debug.patch create mode 100644 pkgs/core/cups/patches/cups-force-gnutls.patch create mode 100644 pkgs/core/cups/patches/cups-getpass.patch create mode 100644 pkgs/core/cups/patches/cups-hostnamelookups.patch create mode 100644 pkgs/core/cups/patches/cups-hp-deviceid-oid.patch create mode 100644 pkgs/core/cups/patches/cups-logrotate.patch create mode 100644 pkgs/core/cups/patches/cups-lpr-help.patch create mode 100644 pkgs/core/cups/patches/cups-multilib.patch create mode 100644 pkgs/core/cups/patches/cups-no-export-ssllibs.patch create mode 100644 pkgs/core/cups/patches/cups-no-gzip-man.patch create mode 100644 pkgs/core/cups/patches/cups-page-label.patch create mode 100644 pkgs/core/cups/patches/cups-peercred.patch create mode 100644 pkgs/core/cups/patches/cups-pid.patch create mode 100644 pkgs/core/cups/patches/cups-res_init.patch create mode 100644 pkgs/core/cups/patches/cups-ricoh-deviceid-oid.patch create mode 100644 pkgs/core/cups/patches/cups-serial.patch create mode 100644 pkgs/core/cups/patches/cups-serialize-gnutls.patch create mode 100644 pkgs/core/cups/patches/cups-serverbin-compat.patch create mode 100644 pkgs/core/cups/patches/cups-snmp-quirks.patch create mode 100644 pkgs/core/cups/patches/cups-str3382.patch create mode 100644 pkgs/core/cups/patches/cups-str3754.patch create mode 100644 pkgs/core/cups/patches/cups-strict-ppd-line-length.patch create mode 100644 pkgs/core/cups/patches/cups-texttops-rotate-page.patch create mode 100644 pkgs/core/cups/patches/cups-uri-compat.patch create mode 100644 pkgs/core/cups/patches/cups-usb-paperout.patch create mode 100644 pkgs/core/cups/patches/cups-x-lspp.patch delete mode 100644 pkgs/core/libnih/patches/libnih-1.0.2-upstream-1.patch
Difference in files: diff --git a/pkgs/core/coreutils/coreutils.nm b/pkgs/core/coreutils/coreutils.nm index 748d142..99b9d3f 100644 --- a/pkgs/core/coreutils/coreutils.nm +++ b/pkgs/core/coreutils/coreutils.nm @@ -26,7 +26,7 @@ include $(PKGROOT)/Include
PKG_NAME = coreutils PKG_VER = 8.7 -PKG_REL = 0 +PKG_REL = 1
PKG_MAINTAINER = PKG_GROUP = System/Base @@ -40,7 +40,7 @@ define PKG_DESCRIPTION endef
PKG_BUILD_DEPS+= autoconf automake libacl-devel libattr-devel libcap \ - ncurses-devel e2fsprogs pam-devel libselinux-devel + libselinux-devel ncurses-devel e2fsprogs pam-devel
PKG_TARBALL = $(THISAPP).tar.gz
@@ -48,6 +48,7 @@ CFLAGS += -D_GNU_SOURCE=1 -fno-strict-aliasing
CONFIGURE_OPTIONS += \ --enable-pam \ + --enable-selinux \ --enable-largefile \ --enable-install-program=arch,hostname,su \ --enable-no-install-program=kill,uptime diff --git a/pkgs/core/coreutils/patches/coreutils-selinux.patch b/pkgs/core/coreutils/patches/coreutils-selinux.patch new file mode 100644 index 0000000..4ad7e6b --- /dev/null +++ b/pkgs/core/coreutils/patches/coreutils-selinux.patch @@ -0,0 +1,671 @@ +diff -urNp coreutils-8.7-orig/configure.ac coreutils-8.7/configure.ac +--- coreutils-8.7-orig/configure.ac 2010-11-15 10:03:39.636171519 +0100 ++++ coreutils-8.7/configure.ac 2010-11-15 10:04:08.161930423 +0100 +@@ -133,6 +133,13 @@ if test "$gl_gcc_warnings" = yes; then + AC_SUBST([GNULIB_TEST_WARN_CFLAGS]) + fi + ++dnl Give the chance to enable SELINUX ++AC_ARG_ENABLE(selinux, dnl ++[ --enable-selinux Enable use of the SELINUX libraries], ++[AC_DEFINE(WITH_SELINUX, 1, [Define if you want to use SELINUX]) ++LIB_SELINUX="-lselinux" ++AC_SUBST(LIB_SELINUX)]) ++ + AC_FUNC_FORK + + AC_ARG_ENABLE(pam, AS_HELP_STRING([--disable-pam], +diff -urNp coreutils-8.7-orig/man/chcon.x coreutils-8.7/man/chcon.x +--- coreutils-8.7-orig/man/chcon.x 2009-09-01 13:01:16.000000000 +0200 ++++ coreutils-8.7/man/chcon.x 2010-11-15 10:04:08.161930423 +0100 +@@ -1,4 +1,4 @@ + [NAME] +-chcon - change file security context ++chcon - change file SELinux security context + [DESCRIPTION] + ." Add any additional description here +diff -urNp coreutils-8.7-orig/man/runcon.x coreutils-8.7/man/runcon.x +--- coreutils-8.7-orig/man/runcon.x 2009-09-01 13:01:16.000000000 +0200 ++++ coreutils-8.7/man/runcon.x 2010-11-15 10:04:08.162922322 +0100 +@@ -1,5 +1,5 @@ + [NAME] +-runcon - run command with specified security context ++runcon - run command with specified SELinux security context + [DESCRIPTION] + Run COMMAND with completely-specified CONTEXT, or with current or + transitioned security context modified by one or more of LEVEL, +diff -urNp coreutils-8.7-orig/src/copy.c coreutils-8.7/src/copy.c +--- coreutils-8.7-orig/src/copy.c 2010-10-28 12:31:17.000000000 +0200 ++++ coreutils-8.7/src/copy.c 2010-11-15 10:04:08.165921553 +0100 +@@ -1924,6 +1924,8 @@ copy_internal (char const *src_name, cha + { + /* Here, we are crossing a file system boundary and cp's -x option + is in effect: so don't copy the contents of this directory. */ ++ if (x->preserve_security_context) ++ restore_default_fscreatecon_or_die (); + } + else + { +diff -urNp coreutils-8.7-orig/src/copy.h coreutils-8.7/src/copy.h +--- coreutils-8.7-orig/src/copy.h 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/copy.h 2010-11-15 10:04:08.166925814 +0100 +@@ -158,6 +158,9 @@ struct cp_options + bool preserve_mode; + bool preserve_timestamps; + ++ /* If true, attempt to set specified security context */ ++ bool set_security_context; ++ + /* Enabled for mv, and for cp by the --preserve=links option. + If true, attempt to preserve in the destination files any + logical hard links between the source files. If used with cp's +diff -urNp coreutils-8.7-orig/src/cp.c coreutils-8.7/src/cp.c +--- coreutils-8.7-orig/src/cp.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/cp.c 2010-11-15 10:04:08.168931890 +0100 +@@ -141,6 +141,7 @@ static struct option const long_opts[] = + {"target-directory", required_argument, NULL, 't'}, + {"update", no_argument, NULL, 'u'}, + {"verbose", no_argument, NULL, 'v'}, ++ {"context", required_argument, NULL, 'Z'}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, + {NULL, 0, NULL, 0} +@@ -200,6 +201,9 @@ Mandatory arguments to long options are + all\n\ + "), stdout); + fputs (_("\ ++ -c same as --preserve=context\n\ ++"), stdout); ++ fputs (_("\ + --no-preserve=ATTR_LIST don't preserve the specified attributes\n\ + --parents use full source file name under DIRECTORY\n\ + "), stdout); +@@ -226,6 +230,7 @@ Mandatory arguments to long options are + destination file is missing\n\ + -v, --verbose explain what is being done\n\ + -x, --one-file-system stay on this file system\n\ ++ -Z, --context=CONTEXT set security context of copy to CONTEXT\n\ + "), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); +@@ -780,6 +785,7 @@ cp_option_init (struct cp_options *x) + x->preserve_timestamps = false; + x->preserve_security_context = false; + x->require_preserve_context = false; ++ x->set_security_context = false; + x->preserve_xattr = false; + x->reduce_diagnostics = false; + x->require_preserve_xattr = false; +@@ -927,7 +933,7 @@ main (int argc, char **argv) + we'll actually use backup_suffix_string. */ + backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); + +- while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:T", ++ while ((c = getopt_long (argc, argv, "abcdfHilLnprst:uvxPRS:TZ:", + long_opts, NULL)) + != -1) + { +@@ -974,6 +980,16 @@ main (int argc, char **argv) + copy_contents = true; + break; + ++ case 'c': ++ if ( x.set_security_context ) { ++ (void) fprintf(stderr, "%s: cannot force target context and preserve it\n", argv[0]); ++ exit( 1 ); ++ } ++ else if (selinux_enabled) { ++ x.preserve_security_context = true; ++ x.require_preserve_context = true; ++ } ++ break; + case 'd': + x.preserve_links = true; + x.dereference = DEREF_NEVER; +@@ -1083,6 +1099,27 @@ main (int argc, char **argv) + x.one_file_system = true; + break; + ++ ++ case 'Z': ++ /* politely decline if we're not on a selinux-enabled kernel. */ ++ if( !selinux_enabled ) { ++ fprintf( stderr, "Warning: ignoring --context (-Z). " ++ "It requires a SELinux enabled kernel.\n" ); ++ break; ++ } ++ if ( x.preserve_security_context ) { ++ (void) fprintf(stderr, "%s: cannot force target context to '%s' and preserve it\n", argv[0], optarg); ++ exit( 1 ); ++ } ++ x.set_security_context = true; ++ /* if there's a security_context given set new path ++ components to that context, too */ ++ if ( setfscreatecon(optarg) < 0 ) { ++ (void) fprintf(stderr, _("cannot set default security context %s\n"), optarg); ++ exit( 1 ); ++ } ++ break; ++ + case 'S': + make_backups = true; + backup_suffix_string = optarg; +diff -urNp coreutils-8.7-orig/src/chcon.c coreutils-8.7/src/chcon.c +--- coreutils-8.7-orig/src/chcon.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/chcon.c 2010-11-15 10:04:08.169922391 +0100 +@@ -356,7 +356,7 @@ Usage: %s [OPTION]... CONTEXT FILE...\n\ + "), + program_name, program_name, program_name); + fputs (_("\ +-Change the security context of each FILE to CONTEXT.\n\ ++Change the SELinux security context of each FILE to CONTEXT.\n\ + With --reference, change the security context of each FILE to that of RFILE.\n\ + \n\ + -h, --no-dereference affect symbolic links instead of any referenced file\n\ +diff -urNp coreutils-8.7-orig/src/id.c coreutils-8.7/src/id.c +--- coreutils-8.7-orig/src/id.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/id.c 2010-11-15 10:04:08.170933217 +0100 +@@ -107,7 +107,7 @@ int + main (int argc, char **argv) + { + int optc; +- int selinux_enabled = (is_selinux_enabled () > 0); ++ bool selinux_enabled = (is_selinux_enabled () > 0); + + /* If true, output the list of all group IDs. -G */ + bool just_group_list = false; +diff -urNp coreutils-8.7-orig/src/install.c coreutils-8.7/src/install.c +--- coreutils-8.7-orig/src/install.c 2010-10-15 21:56:29.000000000 +0200 ++++ coreutils-8.7/src/install.c 2010-11-15 10:04:08.171921693 +0100 +@@ -283,6 +283,7 @@ cp_option_init (struct cp_options *x) + x->data_copy_required = true; + x->require_preserve = false; + x->require_preserve_context = false; ++ x->set_security_context = false; + x->require_preserve_xattr = false; + x->recursive = false; + x->sparse_mode = SPARSE_AUTO; +@@ -460,7 +461,7 @@ main (int argc, char **argv) + we'll actually use backup_suffix_string. */ + backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); + +- while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pt:TvS:Z:", long_options, ++ while ((optc = getopt_long (argc, argv, "bcCsDdg:m:o:pPt:TvS:Z:", long_options, + NULL)) != -1) + { + switch (optc) +@@ -534,6 +535,7 @@ main (int argc, char **argv) + error (0, 0, _("WARNING: --preserve_context is deprecated; " + "use --preserve-context instead")); + /* fall through */ ++ case 'P': + case PRESERVE_CONTEXT_OPTION: + if ( ! selinux_enabled) + { +@@ -541,6 +543,10 @@ main (int argc, char **argv) + "this kernel is not SELinux-enabled")); + break; + } ++ if ( x.set_security_context ) { ++ (void) fprintf(stderr, "%s: cannot force target context and preserve it\n", argv[0]); ++ exit( 1 ); ++ } + x.preserve_security_context = true; + use_default_selinux_context = false; + break; +@@ -552,6 +558,7 @@ main (int argc, char **argv) + break; + } + scontext = optarg; ++ x.set_security_context = true; + use_default_selinux_context = false; + break; + case_GETOPT_HELP_CHAR; +@@ -985,8 +992,8 @@ Mandatory arguments to long options are + -v, --verbose print the name of each directory as it is created\n\ + "), stdout); + fputs (_("\ +- --preserve-context preserve SELinux security context\n\ +- -Z, --context=CONTEXT set SELinux security context of files and directories\n\ ++ -P, --preserve-context (SELinux) preserve security context\n\ ++ -Z, --context=CONTEXT (SELinux) set security context of files and directories\n\ + "), stdout); + + fputs (HELP_OPTION_DESCRIPTION, stdout); +diff -urNp coreutils-8.7-orig/src/ls.c coreutils-8.7/src/ls.c +--- coreutils-8.7-orig/src/ls.c 2010-10-25 12:07:57.000000000 +0200 ++++ coreutils-8.7/src/ls.c 2010-11-15 10:04:08.175921763 +0100 +@@ -159,7 +159,8 @@ enum filetype + symbolic_link, + sock, + whiteout, +- arg_directory ++ arg_directory, ++ command_line + }; + + /* Display letters and indicators for each filetype. +@@ -276,6 +277,7 @@ static void queue_directory (char const + static void sort_files (void); + static void parse_ls_color (void); + void usage (int status); ++static void print_scontext_format (const struct fileinfo *f); + + /* Initial size of hash table. + Most hierarchies are likely to be shallower than this. */ +@@ -345,7 +347,7 @@ static struct pending *pending_dirs; + + static struct timespec current_time; + +-static bool print_scontext; ++static int print_scontext = 0; + static char UNKNOWN_SECURITY_CONTEXT[] = "?"; + + /* Whether any of the files has an ACL. This affects the width of the +@@ -385,7 +387,9 @@ enum format + one_per_line, /* -1 */ + many_per_line, /* -C */ + horizontal, /* -x */ +- with_commas /* -m */ ++ with_commas, /* -m */ ++ security_format, /* -Z */ ++ invalid_format + }; + + static enum format format; +@@ -787,6 +791,9 @@ enum + SHOW_CONTROL_CHARS_OPTION, + SI_OPTION, + SORT_OPTION, ++ CONTEXT_OPTION, ++ LCONTEXT_OPTION, ++ SCONTEXT_OPTION, + TIME_OPTION, + TIME_STYLE_OPTION + }; +@@ -832,7 +839,9 @@ static struct option const long_options[ + {"time-style", required_argument, NULL, TIME_STYLE_OPTION}, + {"color", optional_argument, NULL, COLOR_OPTION}, + {"block-size", required_argument, NULL, BLOCK_SIZE_OPTION}, +- {"context", no_argument, 0, 'Z'}, ++ {"context", no_argument, 0, CONTEXT_OPTION}, ++ {"lcontext", no_argument, 0, LCONTEXT_OPTION}, ++ {"scontext", no_argument, 0, SCONTEXT_OPTION}, + {"author", no_argument, NULL, AUTHOR_OPTION}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, +@@ -842,12 +851,12 @@ static struct option const long_options[ + static char const *const format_args[] = + { + "verbose", "long", "commas", "horizontal", "across", +- "vertical", "single-column", NULL ++ "vertical", "single-column", "context", NULL + }; + static enum format const format_types[] = + { + long_format, long_format, with_commas, horizontal, horizontal, +- many_per_line, one_per_line ++ many_per_line, one_per_line, security_format + }; + ARGMATCH_VERIFY (format_args, format_types); + +@@ -1289,7 +1298,8 @@ main (int argc, char **argv) + /* Avoid following symbolic links when possible. */ + if (is_colored (C_ORPHAN) + || (is_colored (C_EXEC) && color_symlink_as_referent) +- || (is_colored (C_MISSING) && format == long_format)) ++ || (is_colored (C_MISSING) && (format == long_format ++ || format == security_format))) + check_symlink_color = true; + + /* If the standard output is a controlling terminal, watch out +@@ -1336,7 +1346,7 @@ main (int argc, char **argv) + if (dereference == DEREF_UNDEFINED) + dereference = ((immediate_dirs + || indicator_style == classify +- || format == long_format) ++ || format == long_format || format == security_format) + ? DEREF_NEVER + : DEREF_COMMAND_LINE_SYMLINK_TO_DIR); + +@@ -1356,7 +1366,7 @@ main (int argc, char **argv) + + format_needs_stat = sort_type == sort_time || sort_type == sort_size + || format == long_format +- || print_scontext ++ || format == security_format || print_scontext + || print_block_size; + format_needs_type = (! format_needs_stat + && (recursive +@@ -1387,7 +1397,7 @@ main (int argc, char **argv) + } + else + do +- gobble_file (argv[i++], unknown, NOT_AN_INODE_NUMBER, true, ""); ++ gobble_file (argv[i++], command_line, NOT_AN_INODE_NUMBER, true, ""); + while (i < argc); + + if (cwd_n_used) +@@ -1558,7 +1568,7 @@ decode_switches (int argc, char **argv) + ignore_mode = IGNORE_DEFAULT; + ignore_patterns = NULL; + hide_patterns = NULL; +- print_scontext = false; ++ print_scontext = 0; + + /* FIXME: put this in a function. */ + { +@@ -1940,13 +1950,27 @@ decode_switches (int argc, char **argv) + break; + + case 'Z': +- print_scontext = true; ++ print_scontext = 1; ++ format = security_format; + break; + + case_GETOPT_HELP_CHAR; + + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + ++ case CONTEXT_OPTION: /* default security context format */ ++ print_scontext = 1; ++ format = security_format; ++ break; ++ case LCONTEXT_OPTION: /* long format plus security context */ ++ print_scontext = 1; ++ format = long_format; ++ break; ++ case SCONTEXT_OPTION: /* short form of new security format */ ++ print_scontext = 0; ++ format = security_format; ++ break; ++ + default: + usage (LS_FAILURE); + } +@@ -2690,8 +2714,10 @@ clear_files (void) + struct fileinfo *f = sorted_file[i]; + free (f->name); + free (f->linkname); +- if (f->scontext != UNKNOWN_SECURITY_CONTEXT) +- freecon (f->scontext); ++ if (f->scontext != UNKNOWN_SECURITY_CONTEXT) { ++ freecon (f->scontext); ++ f->scontext = NULL; ++ } + } + + cwd_n_used = 0; +@@ -2733,6 +2759,7 @@ gobble_file (char const *name, enum file + memset (f, '\0', sizeof *f); + f->stat.st_ino = inode; + f->filetype = type; ++ f->scontext = NULL; + + if (command_line_arg + || format_needs_stat +@@ -2842,7 +2869,7 @@ gobble_file (char const *name, enum file + && print_with_color && is_colored (C_CAP)) + f->has_capability = has_capability (absolute_name); + +- if (format == long_format || print_scontext) ++ if (format == long_format || format == security_format || print_scontext) + { + bool have_selinux = false; + bool have_acl = false; +@@ -2865,7 +2892,7 @@ gobble_file (char const *name, enum file + err = 0; + } + +- if (err == 0 && format == long_format) ++ if (err == 0 && (format == long_format || format == security_format)) + { + int n = file_has_acl (absolute_name, &f->stat); + err = (n < 0); +@@ -2884,7 +2911,8 @@ gobble_file (char const *name, enum file + } + + if (S_ISLNK (f->stat.st_mode) +- && (format == long_format || check_symlink_color)) ++ && (format == long_format || format == security_format ++ || check_symlink_color)) + { + char *linkname; + struct stat linkstats; +@@ -2904,6 +2932,7 @@ gobble_file (char const *name, enum file + command line are automatically traced if not being + listed as files. */ + if (!command_line_arg || format == long_format ++ || format == security_format + || !S_ISDIR (linkstats.st_mode)) + { + /* Get the linked-to file's mode for the filetype indicator +@@ -2943,7 +2972,7 @@ gobble_file (char const *name, enum file + block_size_width = len; + } + +- if (format == long_format) ++ if (format == long_format || format == security_format) + { + if (print_owner) + { +@@ -3444,6 +3473,13 @@ print_current_files (void) + print_long_format (sorted_file[i]); + DIRED_PUTCHAR ('\n'); + } ++ break; ++ case security_format: ++ for (i = 0; i < cwd_n_used; i++) ++ { ++ print_scontext_format (sorted_file[i]); ++ DIRED_PUTCHAR ('\n'); ++ } + break; + } + } +@@ -3606,6 +3642,67 @@ format_inode (char *buf, size_t buflen, + : (char *) "?"); + } + ++/* Print info about f in scontext format */ ++static void ++print_scontext_format (const struct fileinfo *f) ++{ ++ char modebuf[12]; ++ ++ /* 7 fields that may require LONGEST_HUMAN_READABLE bytes, ++ 1 10-byte mode string, ++ 9 spaces, one following each of these fields, and ++ 1 trailing NUL byte. */ ++ ++ char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10 + 9 + 1]; ++ char *buf = init_bigbuf; ++ char *p; ++ ++ p = buf; ++ ++ if ( print_scontext ) { /* zero means terse listing */ ++ filemodestring (&f->stat, modebuf); ++ if (! any_has_acl) ++ modebuf[10] = '\0'; ++ else if (f->acl_type == ACL_T_SELINUX_ONLY) ++ modebuf[10] = '.'; ++ else if (f->acl_type == ACL_T_YES) ++ modebuf[10] = '+'; ++ modebuf[11] = '\0'; ++ ++ /* print mode */ ++ ++ (void) sprintf (p, "%s ", modebuf); ++ p += strlen (p); ++ ++ /* print standard user and group */ ++ ++ DIRED_FPUTS (buf, stdout, p - buf); ++ format_user (f->stat.st_uid, owner_width, f->stat_ok); ++ format_group (f->stat.st_gid, group_width, f->stat_ok); ++ p = buf; ++ } ++ ++ (void) sprintf (p, "%-32s ", f->scontext ?: ""); ++ p += strlen (p); ++ ++ DIRED_INDENT (); ++ DIRED_FPUTS (buf, stdout, p - buf); ++ size_t w = print_name_with_quoting (f, false, &dired_obstack, p - buf); ++ ++ if (f->filetype == symbolic_link) { ++ if (f->linkname) { ++ DIRED_FPUTS_LITERAL (" -> ", stdout); ++ print_name_with_quoting (f, true, NULL, (p - buf) + w + 4); ++ if (indicator_style != none) ++ print_type_indicator (f->stat_ok, f->linkmode, f->filetype); ++ } ++ } ++ else { ++ if (indicator_style != none) ++ print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype); ++ } ++} ++ + /* Print information about F in long format. */ + static void + print_long_format (const struct fileinfo *f) +@@ -3697,9 +3794,15 @@ print_long_format (const struct fileinfo + The latter is wrong when nlink_width is zero. */ + p += strlen (p); + ++ if (print_scontext) ++ { ++ sprintf (p, "%-32s ", f->scontext ? f->scontext : ""); ++ p += strlen (p); ++ } ++ + DIRED_INDENT (); + +- if (print_owner || print_group || print_author || print_scontext) ++ if (print_owner || print_group || print_author) + { + DIRED_FPUTS (buf, stdout, p - buf); + +@@ -3712,9 +3815,6 @@ print_long_format (const struct fileinfo + if (print_author) + format_user (f->stat.st_author, author_width, f->stat_ok); + +- if (print_scontext) +- format_user_or_group (f->scontext, 0, scontext_width); +- + p = buf; + } + +@@ -4059,9 +4159,6 @@ print_file_name_and_frills (const struct + : human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts, + ST_NBLOCKSIZE, output_block_size)); + +- if (print_scontext) +- printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext); +- + size_t width = print_name_with_quoting (f, false, NULL, start_col); + + if (indicator_style != none) +@@ -4265,9 +4362,6 @@ length_of_file_name_and_frills (const st + output_block_size)) + : block_size_width); + +- if (print_scontext) +- len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width); +- + quote_name (NULL, f->name, filename_quoting_options, &name_width); + len += name_width; + +@@ -4700,9 +4794,16 @@ Mandatory arguments to long options are + -w, --width=COLS assume screen width instead of current value\n\ + -x list entries by lines instead of by columns\n\ + -X sort alphabetically by entry extension\n\ +- -Z, --context print any SELinux security context of each file\n\ + -1 list one file per line\n\ + "), stdout); ++ fputs(_("\nSELinux options:\n\n\ ++ --lcontext Display security context. Enable -l. Lines\n\ ++ will probably be too wide for most displays.\n\ ++ -Z, --context Display security context so it fits on most\n\ ++ displays. Displays only mode, user, group,\n\ ++ security context and file name.\n\ ++ --scontext Display only security context and file name.\n\ ++"), stdout); + fputs (HELP_OPTION_DESCRIPTION, stdout); + fputs (VERSION_OPTION_DESCRIPTION, stdout); + emit_size_note (); +diff -urNp coreutils-8.7-orig/src/mkdir.c coreutils-8.7/src/mkdir.c +--- coreutils-8.7-orig/src/mkdir.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/mkdir.c 2010-11-15 10:04:08.177942716 +0100 +@@ -38,6 +38,7 @@ + static struct option const longopts[] = + { + {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, ++ {"context", required_argument, NULL, 'Z'}, + {"mode", required_argument, NULL, 'm'}, + {"parents", no_argument, NULL, 'p'}, + {"verbose", no_argument, NULL, 'v'}, +diff -urNp coreutils-8.7-orig/src/mknod.c coreutils-8.7/src/mknod.c +--- coreutils-8.7-orig/src/mknod.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/mknod.c 2010-11-15 10:04:08.177942716 +0100 +@@ -35,7 +35,7 @@ + + static struct option const longopts[] = + { +- {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, ++ {GETOPT_SELINUX_CONTEXT_OPTION_DECL}, + {"mode", required_argument, NULL, 'm'}, + {GETOPT_HELP_OPTION_DECL}, + {GETOPT_VERSION_OPTION_DECL}, +diff -urNp coreutils-8.7-orig/src/mv.c coreutils-8.7/src/mv.c +--- coreutils-8.7-orig/src/mv.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/mv.c 2010-11-15 10:04:08.179924138 +0100 +@@ -118,6 +118,7 @@ cp_option_init (struct cp_options *x) + x->preserve_mode = true; + x->preserve_timestamps = true; + x->preserve_security_context = selinux_enabled; ++ x->set_security_context = false; + x->reduce_diagnostics = false; + x->data_copy_required = true; + x->require_preserve = false; /* FIXME: maybe make this an option */ +diff -urNp coreutils-8.7-orig/src/runcon.c coreutils-8.7/src/runcon.c +--- coreutils-8.7-orig/src/runcon.c 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/src/runcon.c 2010-11-15 10:04:08.180922252 +0100 +@@ -86,7 +86,7 @@ Usage: %s CONTEXT COMMAND [args]\n\ + or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\ + "), program_name, program_name); + fputs (_("\ +-Run a program in a different security context.\n\ ++Run a program in a different SELinux security context.\n\ + With neither CONTEXT nor COMMAND, print the current security context.\n\ + \n\ + CONTEXT Complete security context\n\ +diff -urNp coreutils-8.7-orig/tests/init.cfg coreutils-8.7/tests/init.cfg +--- coreutils-8.7-orig/tests/init.cfg 2010-11-08 14:10:20.000000000 +0100 ++++ coreutils-8.7/tests/init.cfg 2010-11-15 10:04:08.181922042 +0100 +@@ -216,8 +216,8 @@ skip_if_() + + require_selinux_() + { +- case `ls -Zd .` in +- '? .'|'unlabeled .') ++ case `ls -Zd . | cut -f4 -d" "` in ++ '?'|'unlabeled') + skip_test_ "this system (or maybe just" \ + "the current file system) lacks SELinux support" + ;; +diff -urNp coreutils-8.7-orig/tests/misc/selinux coreutils-8.7/tests/misc/selinux +--- coreutils-8.7-orig/tests/misc/selinux 2010-10-11 19:35:11.000000000 +0200 ++++ coreutils-8.7/tests/misc/selinux 2010-11-15 10:04:08.181922042 +0100 +@@ -44,7 +44,7 @@ chcon $ctx f d p || + + # inspect that context with both ls -Z and stat. + for i in d f p; do +- c=`ls -dogZ $i|cut -d' ' -f3`; test x$c = x$ctx || fail=1 ++ c=`ls -dogZ $i|cut -d' ' -f4`; test x$c = x$ctx || fail=1 + c=`stat --printf %C $i`; test x$c = x$ctx || fail=1 + done + diff --git a/pkgs/core/coreutils/patches/coreutils-selinuxmanpages.patch b/pkgs/core/coreutils/patches/coreutils-selinuxmanpages.patch new file mode 100644 index 0000000..9cbc166 --- /dev/null +++ b/pkgs/core/coreutils/patches/coreutils-selinuxmanpages.patch @@ -0,0 +1,15 @@ +diff -urNp coreutils-6.10-orig/doc/coreutils.texi coreutils-6.10/doc/coreutils.texi +--- coreutils-6.10-orig/doc/coreutils.texi 2008-04-07 17:52:11.000000000 +0200 ++++ coreutils-6.10/doc/coreutils.texi 2008-04-07 18:01:43.000000000 +0200 +@@ -6981,6 +6981,11 @@ for i; do + done + @end example + ++@item -c ++@cindex SELinux security context information, preserving ++Preserve SELinux security context of the original files if possible. ++Some file systems don't support storing of SELinux security context. ++ + @item --copy-contents + @cindex directories, copying recursively + @cindex copying directories recursively diff --git a/pkgs/core/cups/cups.logrotate b/pkgs/core/cups/cups.logrotate new file mode 100644 index 0000000..773c70f --- /dev/null +++ b/pkgs/core/cups/cups.logrotate @@ -0,0 +1,5 @@ +/var/log/cups/*_log { + missingok + notifempty + sharedscripts +} diff --git a/pkgs/core/cups/cups.nm b/pkgs/core/cups/cups.nm index 9b8693f..408990a 100644 --- a/pkgs/core/cups/cups.nm +++ b/pkgs/core/cups/cups.nm @@ -26,7 +26,7 @@ include $(PKGROOT)/Include
PKG_NAME = cups PKG_VER = 1.4.5 -PKG_REL = 0 +PKG_REL = 2
PKG_MAINTAINER = PKG_GROUP = Applications/Printing @@ -34,8 +34,10 @@ PKG_URL = http://cups.org/software.php PKG_LICENSE = GPLv2+ PKG_SUMMARY = The common UNIX printing system.
-PKG_BUILD_DEPS+= cyrus-sasl-devel gcc-c++ ghostscript libjpeg-devel libpng-devel \ - libtiff-devel openldap-devel pam-devel perl python zlib-devel +PKG_BUILD_DEPS+= audit-devel autoconf automake avahi-devel cyrus-sasl-devel \ + gcc-c++ ghostscript gnutls-devel libgcrypt-devel libjpeg-devel libpng-devel \ + libselinux-devel libtiff-devel openldap-devel pam-devel perl pkg-config \ + python zlib-devel PKG_DEPS += ghostscript
define PKG_DESCRIPTION @@ -49,7 +51,19 @@ PKG_PACKAGES += $(PKG_NAME)-devel $(PKG_NAME)-libs
CONFIGURE_OPTIONS += \ --sysconfdir=/etc \ - --localstatedir=/var + --localstatedir=/var \ + --with-log-file-perm=0600 \ + --enable-pie \ + --enable-relro \ + --enable-avahi \ + --enable-lspp \ + --enable-threads \ + --enable-gnutls + +define STAGE_PREPARE_CMDS + cd $(DIR_APP) && aclocal -I config-scripts + cd $(DIR_APP) && autoconf -I config-scripts +endef
define STAGE_INSTALL cd $(DIR_APP) && make install BUILDROOT=$(BUILDROOT) @@ -59,4 +73,8 @@ define STAGE_INSTALL
-mkdir -pv $(BUILDROOT)/etc/cups cp -vf $(DIR_APP)/conf/cupsd.conf $(BUILDROOT)/etc/cups/ + + # Logrotate + -mkdir -pv $(BUILDROOT)/etc/logrotate.d/ + cp -vf $(DIR_SOURCE)/cups.logrotate $(BUILDROOT)/etc/logrotate.d/cups endef diff --git a/pkgs/core/cups/patches/cups-0755.patch b/pkgs/core/cups/patches/cups-0755.patch new file mode 100644 index 0000000..7835592 --- /dev/null +++ b/pkgs/core/cups/patches/cups-0755.patch @@ -0,0 +1,32 @@ +diff -up cups-1.4.5/Makedefs.in.0755 cups-1.4.5/Makedefs.in +--- cups-1.4.5/Makedefs.in.0755 2010-12-06 17:19:03.335315249 +0000 ++++ cups-1.4.5/Makedefs.in 2010-12-06 17:19:03.416307263 +0000 +@@ -41,13 +41,13 @@ SHELL = /bin/sh + # Installation programs... + # + +-INSTALL_BIN = $(LIBTOOL) $(INSTALL) -c -m 555 @INSTALL_STRIP@ ++INSTALL_BIN = $(LIBTOOL) $(INSTALL) -c -m 755 @INSTALL_STRIP@ + INSTALL_CONFIG = $(INSTALL) -c -m @CUPS_CONFIG_FILE_PERM@ + INSTALL_DATA = $(INSTALL) -c -m 444 + INSTALL_DIR = $(INSTALL) -d +-INSTALL_LIB = $(LIBTOOL) $(INSTALL) -c -m 555 @INSTALL_STRIP@ ++INSTALL_LIB = $(LIBTOOL) $(INSTALL) -c -m 755 @INSTALL_STRIP@ + INSTALL_MAN = $(INSTALL) -c -m 444 +-INSTALL_SCRIPT = $(INSTALL) -c -m 555 ++INSTALL_SCRIPT = $(INSTALL) -c -m 755 + + # + # Default user, group, and system groups for the scheduler... +diff -up cups-1.4.5/scheduler/Makefile.0755 cups-1.4.5/scheduler/Makefile +--- cups-1.4.5/scheduler/Makefile.0755 2010-12-06 17:28:58.562552167 +0000 ++++ cups-1.4.5/scheduler/Makefile 2010-12-06 17:29:07.087756415 +0000 +@@ -174,7 +174,7 @@ install-data: + install-exec: + echo Installing programs in $(SBINDIR)... + $(INSTALL_DIR) -m 755 $(SBINDIR) +- $(INSTALL_BIN) -m 500 cupsd $(SBINDIR) ++ $(INSTALL_BIN) -m 755 cupsd $(SBINDIR) + $(INSTALL_BIN) cupsfilter $(SBINDIR) + -if test "x`uname`" = xDarwin; then \ + $(INSTALL_DIR) $(BUILDROOT)/System/Library/Printers/Libraries; \ diff --git a/pkgs/core/cups/patches/cups-1.1.16-system-auth.patch b/pkgs/core/cups/patches/cups-1.1.16-system-auth.patch new file mode 100644 index 0000000..7ce17e5 --- /dev/null +++ b/pkgs/core/cups/patches/cups-1.1.16-system-auth.patch @@ -0,0 +1,39 @@ +diff -up /dev/null cups-1.4.2/conf/cups.password-auth +--- /dev/null 2009-11-10 09:17:06.284031490 +0000 ++++ cups-1.4.2/conf/cups.password-auth 2009-11-10 11:15:42.750666738 +0000 +@@ -0,0 +1,4 @@ ++#%PAM-1.0 ++# Use password-auth common PAM configuration for the daemon ++auth include password-auth ++account include password-auth +diff -up cups-1.4.2/conf/cups.system-auth cups-1.4.2/conf/cups +diff -up /dev/null cups-1.4.2/conf/cups.system-auth +--- /dev/null 2009-11-10 09:17:06.284031490 +0000 ++++ cups-1.4.2/conf/cups.system-auth 2009-11-10 11:15:42.750666738 +0000 +@@ -0,0 +1,3 @@ ++#%PAM-1.0 ++auth include system-auth ++account include system-auth +diff -up cups-1.4.2/conf/Makefile.system-auth cups-1.4.2/conf/Makefile +--- cups-1.4.2/conf/Makefile.system-auth 2009-09-22 22:53:31.000000000 +0100 ++++ cups-1.4.2/conf/Makefile 2009-11-10 11:18:44.188791989 +0000 +@@ -90,10 +90,16 @@ install-data: + done + -if test x$(PAMDIR) != x; then \ + $(INSTALL_DIR) -m 755 $(BUILDROOT)$(PAMDIR); \ +- if test -r $(BUILDROOT)$(PAMDIR)/cups ; then \ +- $(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups.N ; \ ++ if test -f /etc/pam.d/password-auth; then \ ++ $(INSTALL_DATA) cups.password-auth $(BUILDROOT)$(PAMDIR)/cups; \ ++ elif test -f /etc/pam.d/system-auth; then \ ++ $(INSTALL_DATA) cups.system-auth $(BUILDROOT)$(PAMDIR)/cups; \ + else \ +- $(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups ; \ ++ if test -r $(BUILDROOT)$(PAMDIR)/cups ; then \ ++ $(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups.N ; \ ++ else \ ++ $(INSTALL_DATA) $(PAMFILE) $(BUILDROOT)$(PAMDIR)/cups ; \ ++ fi ; \ + fi ; \ + fi + diff --git a/pkgs/core/cups/patches/cups-EAI_AGAIN.patch b/pkgs/core/cups/patches/cups-EAI_AGAIN.patch new file mode 100644 index 0000000..033e7f8 --- /dev/null +++ b/pkgs/core/cups/patches/cups-EAI_AGAIN.patch @@ -0,0 +1,12 @@ +diff -up cups-1.4.2/cups/http-addr.c.EAI_AGAIN cups-1.4.2/cups/http-addr.c +--- cups-1.4.2/cups/http-addr.c.EAI_AGAIN 2010-02-23 10:39:35.038261623 +0000 ++++ cups-1.4.2/cups/http-addr.c 2010-02-23 10:41:14.684385991 +0000 +@@ -253,7 +253,7 @@ httpAddrLookup( + + if (error) + { +- if (error == EAI_FAIL) ++ if (error == EAI_FAIL || error == EAI_AGAIN || error == EAI_NODATA) + cg->need_res_init = 1; + + return (httpAddrString(addr, name, namelen)); diff --git a/pkgs/core/cups/patches/cups-autotype-crash.patch b/pkgs/core/cups/patches/cups-autotype-crash.patch new file mode 100644 index 0000000..ed6cb15 --- /dev/null +++ b/pkgs/core/cups/patches/cups-autotype-crash.patch @@ -0,0 +1,15 @@ +diff -up cups-1.4.4/scheduler/ipp.c.autotype-crash cups-1.4.4/scheduler/ipp.c +--- cups-1.4.4/scheduler/ipp.c.autotype-crash 2010-10-15 15:25:15.093421917 +0100 ++++ cups-1.4.4/scheduler/ipp.c 2010-10-15 15:25:49.645296947 +0100 +@@ -10481,8 +10481,9 @@ send_document(cupsd_client_t *con, /* I + if (!filetype) + filetype = mimeType(MimeDatabase, super, type); + +- cupsdLogJob(job, CUPSD_LOG_DEBUG, "Request file type is %s/%s.", +- filetype->super, filetype->type); ++ if (filetype) ++ cupsdLogJob(job, CUPSD_LOG_DEBUG, "Request file type is %s/%s.", ++ filetype->super, filetype->type); + } + else + filetype = mimeType(MimeDatabase, super, type); diff --git a/pkgs/core/cups/patches/cups-avahi.patch b/pkgs/core/cups/patches/cups-avahi.patch new file mode 100644 index 0000000..b1fc75c --- /dev/null +++ b/pkgs/core/cups/patches/cups-avahi.patch @@ -0,0 +1,3338 @@ +diff -up cups-1.4.5/backend/dnssd.c.avahi cups-1.4.5/backend/dnssd.c +--- cups-1.4.5/backend/dnssd.c.avahi 2010-12-24 13:11:33.760461375 +0000 ++++ cups-1.4.5/backend/dnssd.c 2010-12-24 13:11:38.325341226 +0000 +@@ -15,14 +15,21 @@ + * + * Contents: + * ++ * next_txt_record() - Get next TXT record from a cups_txt_records_t. ++ * parse_txt_record_pair() - Read key/value pair in cups_txt_records_t. + * main() - Browse for printers. + * browse_callback() - Browse devices. + * browse_local_callback() - Browse local devices. + * compare_devices() - Compare two devices. + * exec_backend() - Execute the backend that corresponds to the + * resolved service name. ++ * device_type() - Get DNS-SD type enumeration from string. + * get_device() - Create or update a device. + * query_callback() - Process query data. ++ * avahi_client_callback() - Avahi client callback function. ++ * avahi_query_callback() - Avahi query callback function. ++ * avahi_browse_callback() - Avahi browse callback function. ++ * find_device() - Find a device from its name and domain. + * sigterm_handler() - Handle termination signals... + * unquote() - Unquote a name string. + */ +@@ -33,7 +40,18 @@ + + #include "backend-private.h" + #include <cups/array.h> +-#include <dns_sd.h> ++#ifdef HAVE_DNSSD ++# include <dns_sd.h> ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++# include <avahi-client/client.h> ++# include <avahi-client/lookup.h> ++# include <avahi-common/simple-watch.h> ++# include <avahi-common/domain.h> ++# include <avahi-common/error.h> ++# include <avahi-common/malloc.h> ++#define kDNSServiceMaxDomainName AVAHI_DOMAIN_NAME_MAX ++#endif /* HAVE_AVAHI */ + + + /* +@@ -52,7 +70,12 @@ typedef enum + + typedef struct + { ++#ifdef HAVE_DNSSD + DNSServiceRef ref; /* Service reference for resolve */ ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ int resolved; /* Did we resolve the device? */ ++#endif /* HAVE_AVAHI */ + char *name, /* Service name */ + *domain, /* Domain name */ + *fullName, /* Full name */ +@@ -64,6 +87,20 @@ typedef struct + sent; /* Did we list the device? */ + } cups_device_t; + ++typedef struct ++{ ++ char key[256]; ++ char value[256]; ++ ++#ifdef HAVE_DNSSD ++ const uint8_t *data; ++ const uint8_t *datanext; ++ const uint8_t *dataend; ++#else /* HAVE_AVAHI */ ++ AvahiStringList *txt; ++#endif /* HAVE_DNSSD */ ++} cups_txt_records_t; ++ + + /* + * Local globals... +@@ -77,6 +114,7 @@ static int job_canceled = 0; + * Local functions... + */ + ++#ifdef HAVE_DNSSD + static void browse_callback(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, +@@ -92,12 +130,6 @@ static void browse_local_callback(DNSSe + const char *regtype, + const char *replyDomain, + void *context); +-static int compare_devices(cups_device_t *a, cups_device_t *b); +-static void exec_backend(char **argv); +-static cups_device_t *get_device(cups_array_t *devices, +- const char *serviceName, +- const char *regtype, +- const char *replyDomain); + static void query_callback(DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, +@@ -106,9 +138,118 @@ static void query_callback(DNSServiceRe + uint16_t rrclass, uint16_t rdlen, + const void *rdata, uint32_t ttl, + void *context); ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++static void avahi_client_callback (AvahiClient *client, ++ AvahiClientState state, ++ void *context); ++static void avahi_browse_callback (AvahiServiceBrowser *browser, ++ AvahiIfIndex interface, ++ AvahiProtocol protocol, ++ AvahiBrowserEvent event, ++ const char *serviceName, ++ const char *regtype, ++ const char *replyDomain, ++ AvahiLookupResultFlags flags, ++ void *context); ++#endif /* HAVE_AVAHI */ ++ ++static cups_device_t * find_device (cups_array_t *devices, ++ cups_txt_records_t *txt, ++ cups_device_t *dkey); ++static int compare_devices(cups_device_t *a, cups_device_t *b); ++static void exec_backend(char **argv); ++static cups_device_t *get_device(cups_array_t *devices, ++ const char *serviceName, ++ const char *regtype, ++ const char *replyDomain); + static void sigterm_handler(int sig); + static void unquote(char *dst, const char *src, size_t dstsize); + ++#ifdef HAVE_AVAHI ++static AvahiSimplePoll *simple_poll = NULL; ++static int avahi_got_callback; ++#endif /* HAVE_AVAHI */ ++ ++ ++/* ++ * 'next_txt_record()' - Get next TXT record from a cups_txt_records_t. ++ */ ++ ++static cups_txt_records_t * ++next_txt_record (cups_txt_records_t *txt) ++{ ++#ifdef HAVE_DNSSD ++ txt->data = txt->datanext; ++#else /* HAVE_AVAHI */ ++ txt->txt = avahi_string_list_get_next (txt->txt); ++ if (txt->txt == NULL) ++ return NULL; ++#endif /* HAVE_DNSSD */ ++ ++ return txt; ++} ++ ++ ++/* ++ * 'parse_txt_record_pair()' - Read key/value pair in cups_txt_records_t. ++ */ ++ ++static int ++parse_txt_record_pair (cups_txt_records_t *txt) ++{ ++#ifdef HAVE_DNSSD ++ uint8_t datalen; ++ uint8_t *data = txt->data; ++ char *ptr; ++ ++ /* ++ * Read a key/value pair starting with an 8-bit length. Since the ++ * length is 8 bits and the size of the key/value buffers is 256, we ++ * don't need to check for overflow... ++ */ ++ ++ datalen = *data++; ++ if (!datalen || (data + datalen) >= txt->dataend) ++ return NULL; ++ txt->datanext = data + datalen; ++ ++ for (ptr = txt->key; data < txt->datanext && *data != '='; data ++) ++ *ptr++ = *data; ++ *ptr = '\0'; ++ ++ if (data < txt->datanext && *data == '=') ++ { ++ data++; ++ ++ if (data < datanext) ++ memcpy (txt->value, data, txt->datanext - data); ++ value[txt->datanext - data] = '\0'; ++ } ++ else ++ return 1; ++#else /* HAVE_AVAHI */ ++ char *key, *value; ++ size_t len; ++ avahi_string_list_get_pair (txt->txt, &key, &value, &len); ++ if (len > sizeof (txt->value) - 1) ++ len = sizeof (txt->value) - 1; ++ ++ memcpy (txt->value, value, len); ++ txt->value[len] = '\0'; ++ len = strlen (key); ++ if (len > sizeof (txt->key) - 1) ++ len = sizeof (txt->key) - 1; ++ ++ memcpy (txt->key, key, len); ++ txt->key[len] = '\0'; ++ avahi_free (key); ++ avahi_free (value); ++#endif /* HAVE_AVAHI */ ++ ++ return 0; ++} ++ + + /* + * 'main()' - Browse for printers. +@@ -119,6 +260,13 @@ main(int argc, /* I - Number of comm + char *argv[]) /* I - Command-line arguments */ + { + const char *name; /* Backend name */ ++ cups_array_t *devices; /* Device array */ ++ cups_device_t *device; /* Current device */ ++ char uriName[1024]; /* Unquoted fullName for URI */ ++#ifdef HAVE_DNSSD ++ int fd; /* Main file descriptor */ ++ fd_set input; /* Input set for select() */ ++ struct timeval timeout; /* Timeout for select() */ + DNSServiceRef main_ref, /* Main service reference */ + fax_ipp_ref, /* IPP fax service reference */ + ipp_ref, /* IPP service reference */ +@@ -130,12 +278,11 @@ main(int argc, /* I - Number of comm + pdl_datastream_ref, /* AppSocket service reference */ + printer_ref, /* LPD service reference */ + riousbprint_ref; /* Remote IO service reference */ +- int fd; /* Main file descriptor */ +- fd_set input; /* Input set for select() */ +- struct timeval timeout; /* Timeout for select() */ +- cups_array_t *devices; /* Device array */ +- cups_device_t *device; /* Current device */ +- char uriName[1024]; /* Unquoted fullName for URI */ ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ AvahiClient *client; ++ int error; ++#endif /* HAVE_AVAHI */ + #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ + #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ +@@ -194,6 +341,49 @@ main(int argc, /* I - Number of comm + * Browse for different kinds of printers... + */ + ++#ifdef HAVE_AVAHI ++ if ((simple_poll = avahi_simple_poll_new ()) == NULL) ++ { ++ perror ("ERROR: Unable to create avahi simple poll object"); ++ return (1); ++ } ++ ++ client = avahi_client_new (avahi_simple_poll_get (simple_poll), ++ 0, avahi_client_callback, NULL, &error); ++ if (!client) ++ { ++ perror ("ERROR: Unable to create avahi client"); ++ return (1); ++ } ++ ++ avahi_service_browser_new (client, AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ "_fax-ipp._tcp", NULL, 0, ++ avahi_browse_callback, devices); ++ avahi_service_browser_new (client, AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ "_ipp._tcp", NULL, 0, ++ avahi_browse_callback, devices); ++ avahi_service_browser_new (client, AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ "_ipp-tls._tcp", NULL, 0, ++ avahi_browse_callback, devices); ++ avahi_service_browser_new (client, AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ "_pdl-datastream._tcp", ++ NULL, 0, ++ avahi_browse_callback, ++ devices); ++ avahi_service_browser_new (client, AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ "_printer._tcp", NULL, 0, ++ avahi_browse_callback, devices); ++ avahi_service_browser_new (client, AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ "_riousbprint._tcp", NULL, 0, ++ avahi_browse_callback, devices); ++#endif /* HAVE_AVAHI */ ++#ifdef HAVE_DNSSD + if (DNSServiceCreateConnection(&main_ref) != kDNSServiceErr_NoError) + { + perror("ERROR: Unable to create service connection"); +@@ -245,6 +435,7 @@ main(int argc, /* I - Number of comm + riousbprint_ref = main_ref; + DNSServiceBrowse(&riousbprint_ref, kDNSServiceFlagsShareConnection, 0, + "_riousbprint._tcp", NULL, browse_callback, devices); ++#endif /* HAVE_DNSSD */ + + /* + * Loop until we are killed... +@@ -252,6 +443,9 @@ main(int argc, /* I - Number of comm + + while (!job_canceled) + { ++ int announce = 0; ++ ++#ifdef HAVE_DNSSD + FD_ZERO(&input); + FD_SET(fd, &input); + +@@ -271,11 +465,35 @@ main(int argc, /* I - Number of comm + } + else + { ++ announce = 1; ++ } ++#else /* HAVE_AVAHI */ ++ int r; ++ avahi_got_callback = 0; ++ r = avahi_simple_poll_iterate (simple_poll, 1); ++ if (r != 0 && r != EINTR) ++ { ++ /* ++ * We've been told to exit the loop. Perhaps the connection to ++ * avahi failed. ++ */ ++ ++ break; ++ } ++ ++ if (avahi_got_callback) ++ announce = 1; ++#endif /* HAVE_DNSSD */ ++ ++ if (announce) ++ { + /* + * Announce any devices we've found... + */ + ++#ifdef HAVE_DNSSD + DNSServiceErrorType status; /* DNS query status */ ++#endif /* HAVE_DNSSD */ + cups_device_t *best; /* Best matching device */ + char device_uri[1024]; /* Device URI */ + int count; /* Number of queries */ +@@ -285,6 +503,7 @@ main(int argc, /* I - Number of comm + best = NULL, count = 0; + device; + device = (cups_device_t *)cupsArrayNext(devices)) ++#ifdef HAVE_DNSSD + if (!device->ref && !device->sent) + { + /* +@@ -313,14 +532,23 @@ main(int argc, /* I - Number of comm + count ++; + } + } +- else if (!device->sent) ++ else ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ if (!device->resolved) ++ continue; ++ else ++#endif /* HAVE_AVAHI */ ++ if (!device->sent) + { ++#ifdef HAVE_DNSSD + /* + * Got the TXT records, now report the device... + */ + + DNSServiceRefDeallocate(device->ref); + device->ref = 0; ++#endif /* HAVE_DNSSD */ + + if (!best) + best = device; +@@ -368,6 +596,7 @@ main(int argc, /* I - Number of comm + } + + ++#ifdef HAVE_DNSSD + /* + * 'browse_callback()' - Browse devices. + */ +@@ -456,6 +685,7 @@ browse_local_callback( + device->fullName); + device->sent = 1; + } ++#endif /* HAVE_DNSSD */ + + + /* +@@ -530,6 +760,37 @@ exec_backend(char **argv) /* I - Comman + + + /* ++ * 'device_type()' - Get DNS-SD type enumeration from string. ++ */ ++ ++static int ++device_type (const char *regtype) ++{ ++#ifdef HAVE_AVAHI ++ if (!strcmp(regtype, "_ipp._tcp") || ++ !strcmp(regtype, "_ipp-tls._tcp")) ++ return (CUPS_DEVICE_IPP); ++ else if (!strcmp(regtype, "_fax-ipp._tcp")) ++ return (CUPS_DEVICE_FAX_IPP); ++ else if (!strcmp(regtype, "_printer._tcp")) ++ return (CUPS_DEVICE_PDL_DATASTREAM); ++#else ++ if (!strcmp(regtype, "_ipp._tcp.") || ++ !strcmp(regtype, "_ipp-tls._tcp.")) ++ return (CUPS_DEVICE_IPP); ++ else if (!strcmp(regtype, "_fax-ipp._tcp.")) ++ return (CUPS_DEVICE_FAX_IPP); ++ else if (!strcmp(regtype, "_printer._tcp.")) ++ return (CUPS_DEVICE_PRINTER); ++ else if (!strcmp(regtype, "_pdl-datastream._tcp.")) ++ return (CUPS_DEVICE_PDL_DATASTREAM); ++#endif /* HAVE_AVAHI */ ++ ++ return (CUPS_DEVICE_RIOUSBPRINT); ++} ++ ++ ++/* + * 'get_device()' - Create or update a device. + */ + +@@ -550,18 +811,7 @@ get_device(cups_array_t *devices, /* I - + */ + + key.name = (char *)serviceName; +- +- if (!strcmp(regtype, "_ipp._tcp.") || +- !strcmp(regtype, "_ipp-tls._tcp.")) +- key.type = CUPS_DEVICE_IPP; +- else if (!strcmp(regtype, "_fax-ipp._tcp.")) +- key.type = CUPS_DEVICE_FAX_IPP; +- else if (!strcmp(regtype, "_printer._tcp.")) +- key.type = CUPS_DEVICE_PRINTER; +- else if (!strcmp(regtype, "_pdl-datastream._tcp.")) +- key.type = CUPS_DEVICE_PDL_DATASTREAM; +- else +- key.type = CUPS_DEVICE_RIOUSBPRINT; ++ key.type = device_type (regtype); + + for (device = cupsArrayFind(devices, &key); + device; +@@ -581,8 +831,14 @@ get_device(cups_array_t *devices, /* I - + free(device->domain); + device->domain = strdup(replyDomain); + ++#ifdef HAVE_DNSSD + DNSServiceConstructFullName(fullName, device->name, regtype, + replyDomain); ++#else /* HAVE_AVAHI */ ++ avahi_service_name_join (fullName, kDNSServiceMaxDomainName, ++ serviceName, regtype, replyDomain); ++#endif /* HAVE_DNSSD */ ++ + free(device->fullName); + device->fullName = strdup(fullName); + } +@@ -602,6 +858,9 @@ get_device(cups_array_t *devices, /* I - + device->domain = strdup(replyDomain); + device->type = key.type; + device->priority = 50; ++#ifdef HAVE_AVAHI ++ device->resolved = 0; ++#endif /* HAVE_AVAHI */ + + cupsArrayAdd(devices, device); + +@@ -609,13 +868,20 @@ get_device(cups_array_t *devices, /* I - + * Set the "full name" of this service, which is used for queries... + */ + ++#ifdef HAVE_DNSSD + DNSServiceConstructFullName(fullName, serviceName, regtype, replyDomain); ++#else /* HAVE_AVAHI */ ++ avahi_service_name_join (fullName, kDNSServiceMaxDomainName, ++ serviceName, regtype, replyDomain); ++#endif /* HAVE_DNSSD */ ++ + device->fullName = strdup(fullName); + + return (device); + } + + ++#ifdef HAVE_DNSSD + /* + * 'query_callback()' - Process query data. + */ +@@ -639,7 +905,7 @@ query_callback( + *ptr; /* Pointer into string */ + cups_device_t dkey, /* Search key */ + *device; /* Device */ +- ++ cups_txt_records_t txt; + + fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, " + "interfaceIndex=%d, errorCode=%d, fullName="%s", " +@@ -673,84 +939,232 @@ query_callback( + if ((ptr = strstr(name, "._")) != NULL) + *ptr = '\0'; + +- if (strstr(fullName, "_ipp._tcp.") || +- strstr(fullName, "_ipp-tls._tcp.")) +- dkey.type = CUPS_DEVICE_IPP; +- else if (strstr(fullName, "_fax-ipp._tcp.")) +- dkey.type = CUPS_DEVICE_FAX_IPP; +- else if (strstr(fullName, "_printer._tcp.")) +- dkey.type = CUPS_DEVICE_PRINTER; +- else if (strstr(fullName, "_pdl-datastream._tcp.")) +- dkey.type = CUPS_DEVICE_PDL_DATASTREAM; ++ dkey.type = device_type (fullName); ++ ++ txt.data = rdata; ++ txt.dataend = rdata + rdlen; ++ device = find_device ((cups_array_t *) context, &txt, &dkey); ++ if (!device) ++ fprintf(stderr, "DEBUG: Ignoring TXT record for "%s"...\n", fullName); ++} ++#endif /* HAVE_DNSSD */ ++ ++ ++#ifdef HAVE_AVAHI ++/* ++ * 'avahi_client_callback()' - Avahi client callback function. ++ */ ++ ++static void ++avahi_client_callback(AvahiClient *client, ++ AvahiClientState state, ++ void *context) ++{ ++ /* ++ * If the connection drops, quit. ++ */ ++ ++ if (state == AVAHI_CLIENT_FAILURE) ++ { ++ fprintf (stderr, "ERROR: Avahi connection failed\n"); ++ avahi_simple_poll_quit (simple_poll); ++ } ++} ++ ++ ++/* ++ * 'avahi_query_callback()' - Avahi query callback function. ++ */ ++ ++static void ++avahi_query_callback(AvahiServiceResolver *resolver, ++ AvahiIfIndex interface, ++ AvahiProtocol protocol, ++ AvahiResolverEvent event, ++ const char *name, ++ const char *type, ++ const char *domain, ++ const char *host_name, ++ const AvahiAddress *address, ++ uint16_t port, ++ AvahiStringList *txt, ++ AvahiLookupResultFlags flags, ++ void *context) ++{ ++ AvahiClient *client; ++ cups_device_t key, ++ *device; ++ char uqname[1024], ++ *ptr; ++ cups_txt_records_t txtr; ++ ++ client = avahi_service_resolver_get_client (resolver); ++ if (event != AVAHI_RESOLVER_FOUND) ++ { ++ if (event == AVAHI_RESOLVER_FAILURE) ++ { ++ fprintf (stderr, "ERROR: %s\n", ++ avahi_strerror (avahi_client_errno (client))); ++ } ++ ++ avahi_service_resolver_free (resolver); ++ return; ++ } ++ ++ /* ++ * Set search key for device. ++ */ ++ ++ key.name = uqname; ++ unquote (uqname, name, sizeof (uqname)); ++ if ((ptr = strstr(name, "._")) != NULL) ++ *ptr = '\0'; ++ ++ key.domain = (char *) domain; ++ key.type = device_type (type); ++ ++ /* ++ * Find the device and the the TXT information. ++ */ ++ ++ txtr.txt = txt; ++ device = find_device ((cups_array_t *) context, &txtr, &key); ++ if (device) ++ { ++ /* ++ * Let the main loop know to announce the device. ++ */ ++ ++ device->resolved = 1; ++ avahi_got_callback = 1; ++ } + else +- dkey.type = CUPS_DEVICE_RIOUSBPRINT; ++ fprintf (stderr, "DEBUG: Ignoring TXT record for "%s"...\n", name); ++ ++ avahi_service_resolver_free (resolver); ++} ++ ++ ++/* ++ * 'avahi_browse_callback()' - Avahi browse callback function. ++ */ ++ ++static void ++avahi_browse_callback(AvahiServiceBrowser *browser, ++ AvahiIfIndex interface, ++ AvahiProtocol protocol, ++ AvahiBrowserEvent event, ++ const char *name, ++ const char *type, ++ const char *domain, ++ AvahiLookupResultFlags flags, ++ void *context) ++{ ++ AvahiClient *client = avahi_service_browser_get_client (browser); + +- for (device = cupsArrayFind(devices, &dkey); ++ switch (event) ++ { ++ case AVAHI_BROWSER_FAILURE: ++ fprintf (stderr, "ERROR: %s\n", ++ avahi_strerror (avahi_client_errno (client))); ++ avahi_simple_poll_quit (simple_poll); ++ return; ++ ++ case AVAHI_BROWSER_NEW: ++ /* ++ * This object is new on the network. ++ */ ++ ++ if (flags & AVAHI_LOOKUP_RESULT_LOCAL) ++ { ++ /* ++ * This comes from the local machine so ignore it. ++ */ ++ ++ fprintf (stderr, "DEBUG: ignoring local service %s\n", name); ++ } ++ else ++ { ++ /* ++ * Create a device entry for it if it doesn't yet exist. ++ */ ++ ++ get_device ((cups_array_t *)context, name, type, domain); ++ ++ /* ++ * Now look for a TXT entry. ++ */ ++ ++ if (avahi_service_resolver_new (client, interface, protocol, ++ name, type, domain, ++ AVAHI_PROTO_UNSPEC, 0, ++ avahi_query_callback, context) == NULL) ++ { ++ fprintf (stderr, "ERROR: failed to resolve service %s: %s\n", ++ name, avahi_strerror (avahi_client_errno (client))); ++ } ++ } ++ ++ break; ++ ++ case AVAHI_BROWSER_REMOVE: ++ case AVAHI_BROWSER_ALL_FOR_NOW: ++ case AVAHI_BROWSER_CACHE_EXHAUSTED: ++ break; ++ } ++} ++#endif /* HAVE_AVAHI */ ++ ++ ++/* ++ * 'find_device()' - Find a device from its name and domain. ++ */ ++ ++static cups_device_t * ++find_device (cups_array_t *devices, ++ cups_txt_records_t *txt, ++ cups_device_t *dkey) ++{ ++ cups_device_t *device; ++ char *ptr; ++ ++ for (device = cupsArrayFind(devices, dkey); + device; + device = cupsArrayNext(devices)) + { +- if (strcasecmp(device->name, dkey.name) || +- strcasecmp(device->domain, dkey.domain)) ++ if (strcasecmp(device->name, dkey->name) || ++ strcasecmp(device->domain, dkey->domain)) + { + device = NULL; + break; + } +- else if (device->type == dkey.type) ++ else if (device->type == dkey->type) + { + /* + * Found it, pull out the priority and make and model from the TXT + * record and save it... + */ + +- const uint8_t *data, /* Pointer into data */ +- *datanext, /* Next key/value pair */ +- *dataend; /* End of entire TXT record */ +- uint8_t datalen; /* Length of current key/value pair */ +- char key[256], /* Key string */ +- value[256], /* Value string */ +- make_and_model[512], ++ char make_and_model[512], + /* Manufacturer and model */ + model[256], /* Model */ +- device_id[2048];/* 1284 device ID */ +- ++ device_id[2048]; /* 1284 device ID */ + + device_id[0] = '\0'; + make_and_model[0] = '\0'; + + strcpy(model, "Unknown"); + +- for (data = rdata, dataend = data + rdlen; +- data < dataend; +- data = datanext) ++ for (;;) + { +- /* +- * Read a key/value pair starting with an 8-bit length. Since the +- * length is 8 bits and the size of the key/value buffers is 256, we +- * don't need to check for overflow... +- */ +- +- datalen = *data++; +- +- if (!datalen || (data + datalen) >= dataend) +- break; ++ char *key; ++ char *value; + +- datanext = data + datalen; +- +- for (ptr = key; data < datanext && *data != '='; data ++) +- *ptr++ = *data; +- *ptr = '\0'; +- +- if (data < datanext && *data == '=') +- { +- data ++; +- +- if (data < datanext) +- memcpy(value, data, datanext - data); +- value[datanext - data] = '\0'; +- } +- else +- continue; ++ if (parse_txt_record_pair (txt)) ++ goto next; + ++ key = txt->key; ++ value = txt->value; + if (!strncasecmp(key, "usb_", 4)) + { + /* +@@ -805,6 +1219,10 @@ query_callback( + if (device->type == CUPS_DEVICE_PRINTER) + device->sent = 1; + } ++ ++ next: ++ if (next_txt_record (txt) == NULL) ++ break; + } + + if (device->device_id) +@@ -861,11 +1279,9 @@ query_callback( + } + } + +- if (!device) +- fprintf(stderr, "DEBUG: Ignoring TXT record for "%s"...\n", fullName); ++ return device; + } + +- + /* + * 'sigterm_handler()' - Handle termination signals... + */ +diff -up cups-1.4.5/config.h.in.avahi cups-1.4.5/config.h.in +--- cups-1.4.5/config.h.in.avahi 2010-08-13 05:11:46.000000000 +0100 ++++ cups-1.4.5/config.h.in 2010-12-24 13:11:38.327341170 +0000 +@@ -344,6 +344,13 @@ + + + /* ++ * Do we have Avahi for DNS Service Discovery? ++ */ ++ ++#undef HAVE_AVAHI ++ ++ ++/* + * Do we have <sys/ioctl.h>? + */ + +diff -up cups-1.4.5/config-scripts/cups-dnssd.m4.avahi cups-1.4.5/config-scripts/cups-dnssd.m4 +--- cups-1.4.5/config-scripts/cups-dnssd.m4.avahi 2009-08-28 23:54:34.000000000 +0100 ++++ cups-1.4.5/config-scripts/cups-dnssd.m4 2010-12-24 13:11:38.326341199 +0000 +@@ -27,6 +27,21 @@ AC_ARG_WITH(dnssd-includes, [ --with-dn + DNSSDLIBS="" + DNSSD_BACKEND="" + ++AC_ARG_ENABLE(avahi, [ --enable-avahi turn on DNS Service Discovery support, default=no], ++ [if test x$enable_avahi = xyes; then ++ AC_MSG_CHECKING(for Avahi) ++ if $PKGCONFIG --exists avahi-client; then ++ AC_MSG_RESULT(yes) ++ CFLAGS="$CFLAGS `$PKGCONFIG --cflags avahi-client`" ++ DNSSDLIBS="`$PKGCONFIG --libs avahi-client`" ++ DNSSD_BACKEND="dnssd" ++ AC_DEFINE(HAVE_AVAHI) ++ enable_dnssd=no ++ else ++ AC_MSG_RESULT(no) ++ fi ++ fi]) ++ + if test x$enable_dnssd != xno; then + AC_CHECK_HEADER(dns_sd.h, [ + case "$uname" in +diff -up cups-1.4.5/cups/http-support.c.avahi cups-1.4.5/cups/http-support.c +--- cups-1.4.5/cups/http-support.c.avahi 2010-10-01 23:40:38.000000000 +0100 ++++ cups-1.4.5/cups/http-support.c 2010-12-24 13:11:38.330341093 +0000 +@@ -41,6 +41,10 @@ + * http_copy_decode() - Copy and decode a URI. + * http_copy_encode() - Copy and encode a URI. + * resolve_callback() - Build a device URI for the given service name. ++ * avahi_resolve_uri_client_cb() ++ * - Avahi client callback for resolving URI. ++ * avahi_resolve_uri_resolver_cb() ++ * - Avahi resolver callback for resolving URI. + */ + + /* +@@ -55,6 +59,11 @@ + # include <dns_sd.h> + # include <poll.h> + #endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++# include <avahi-client/client.h> ++# include <avahi-client/lookup.h> ++# include <avahi-common/simple-watch.h> ++#endif /* HAVE_AVAHI */ + + + /* +@@ -121,6 +130,24 @@ static void resolve_callback(DNSService + void *context); + #endif /* HAVE_DNSSD */ + ++#ifdef HAVE_AVAHI ++static void avahi_resolve_uri_client_cb(AvahiClient *client, ++ AvahiClientState state, ++ void *simple_poll); ++static void avahi_resolve_uri_resolver_cb(AvahiServiceResolver *resolver, ++ AvahiIfIndex interface, ++ AvahiProtocol protocol, ++ AvahiResolverEvent event, ++ const char *name, ++ const char *type, ++ const char *domain, ++ const char *host_name, ++ const AvahiAddress *address, ++ uint16_t port, ++ AvahiStringList *txt, ++ AvahiLookupResultFlags flags, ++ void *context); ++#endif /* HAVE_AVAHI */ + + /* + * 'httpAssembleURI()' - Assemble a uniform resource identifier from its +@@ -1351,6 +1378,9 @@ _httpResolveURI( + + if (strstr(hostname, "._tcp")) + { ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++ char *regtype, /* Pointer to type in hostname */ ++ *domain; /* Pointer to domain in hostname */ + #ifdef HAVE_DNSSD + DNSServiceRef ref, /* DNS-SD master service reference */ + domainref, /* DNS-SD service reference for domain */ +@@ -1361,6 +1391,16 @@ _httpResolveURI( + *domain; /* Pointer to domain in hostname */ + _http_uribuf_t uribuf; /* URI buffer */ + struct pollfd polldata; /* Polling data */ ++#else /* HAVE_AVAHI */ ++ AvahiSimplePoll *simple_poll; ++ AvahiClient *client; ++ int error; ++ struct ++ { ++ AvahiSimplePoll *poll; ++ _http_uribuf_t uribuf; ++ } user_data; ++#endif /* HAVE_DNSSD */ + + + if (logit) +@@ -1398,8 +1438,13 @@ _httpResolveURI( + if (domain) + *domain++ = '\0'; + ++#ifdef HAVE_DNSSD + uribuf.buffer = resolved_uri; + uribuf.bufsize = resolved_size; ++#else ++ user_data.uribuf.buffer = resolved_uri; ++ user_data.uribuf.bufsize = resolved_size; ++#endif + + resolved_uri[0] = '\0'; + +@@ -1414,6 +1459,7 @@ _httpResolveURI( + + uri = NULL; + ++#ifdef HAVE_DNSSD + if (DNSServiceCreateConnection(&ref) == kDNSServiceErr_NoError) + { + localref = ref; +@@ -1500,6 +1546,36 @@ _httpResolveURI( + + DNSServiceRefDeallocate(ref); + } ++#else /* HAVE_AVAHI */ ++ if ((simple_poll = avahi_simple_poll_new ()) != NULL) ++ { ++ if ((client = avahi_client_new (avahi_simple_poll_get (simple_poll), ++ 0, avahi_resolve_uri_client_cb, ++ &simple_poll, &error)) != NULL) ++ { ++ user_data.poll = simple_poll; ++ if (avahi_service_resolver_new (client, AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, hostname, ++ regtype, domain, AVAHI_PROTO_UNSPEC, 0, ++ avahi_resolve_uri_resolver_cb, ++ &user_data) != NULL) ++ { ++ avahi_simple_poll_loop (simple_poll); ++ ++ /* ++ * Collect the result. ++ */ ++ ++ if (resolved_uri[0]) ++ uri = resolved_uri; ++ } ++ ++ avahi_client_free (client); ++ } ++ ++ avahi_simple_poll_free (simple_poll); ++ } ++#endif /* HAVE_DNSSD */ + + if (logit) + { +@@ -1511,13 +1587,13 @@ _httpResolveURI( + fputs("STATE: -connecting-to-device,offline-report\n", stderr); + } + +-#else ++#else /* HAVE_DNSSD || HAVE_AVAHI */ + /* + * No DNS-SD support... + */ + + uri = NULL; +-#endif /* HAVE_DNSSD */ ++#endif /* HAVE_DNSSD || HAVE_AVAHI */ + + if (logit && !uri) + _cupsLangPuts(stderr, _("Unable to find printer!\n")); +@@ -1723,6 +1799,116 @@ resolve_callback( + #endif /* HAVE_DNSSD */ + + ++#ifdef HAVE_AVAHI ++/* ++ * 'avahi_resolve_uri_client_cb()' - Avahi client callback for resolving URI. ++ */ ++ ++static void ++avahi_resolve_uri_client_cb (AvahiClient *client, ++ AvahiClientState state, ++ void *simple_poll) ++{ ++ DEBUG_printf(("avahi_resolve_uri_client_callback(client=%p, state=%d, " ++ "simple_poll=%p)\n", client, state, simple_poll)); ++ ++ /* ++ * If the connection drops, quit. ++ */ ++ ++ if (state == AVAHI_CLIENT_FAILURE) ++ avahi_simple_poll_quit (simple_poll); ++} ++ ++ ++/* ++ * 'avahi_resolve_uri_resolver_cb()' - Avahi resolver callback for resolving ++ * URI. ++ */ ++ ++static void ++avahi_resolve_uri_resolver_cb (AvahiServiceResolver *resolver, ++ AvahiIfIndex interface, ++ AvahiProtocol protocol, ++ AvahiResolverEvent event, ++ const char *name, ++ const char *type, ++ const char *domain, ++ const char *host_name, ++ const AvahiAddress *address, ++ uint16_t port, ++ AvahiStringList *txt, ++ AvahiLookupResultFlags flags, ++ void *context) ++{ ++ const char *scheme; /* URI scheme */ ++ char rp[256]; /* Remote printer */ ++ AvahiStringList *pair; ++ char *value; ++ size_t valueLen = 0; ++ char addr[AVAHI_ADDRESS_STR_MAX]; ++ struct ++ { ++ AvahiSimplePoll *poll; ++ _http_uribuf_t uribuf; ++ } *poll_uribuf = context; ++ ++ DEBUG_printf(("avahi_resolve_uri_resolver_callback(resolver=%p, " ++ "interface=%d, protocol=%d, event=%d, name="%s", " ++ "type="%s", domain="%s", host_name="%s", address=%p, " ++ "port=%d, txt=%p, flags=%d, context=%p)\n", ++ resolver, interface, protocol, event, name, type, domain, ++ host_name, address, port, txt, flags, context)); ++ ++ if (event != AVAHI_RESOLVER_FOUND) ++ { ++ avahi_service_resolver_free (resolver); ++ avahi_simple_poll_quit (poll_uribuf->poll); ++ return; ++ } ++ ++ /* ++ * Figure out the scheme from the full name... ++ */ ++ ++ if (strstr(type, "_ipp.")) ++ scheme = "ipp"; ++ else if (strstr(type, "_printer.")) ++ scheme = "lpd"; ++ else if (strstr(type, "_pdl-datastream.")) ++ scheme = "socket"; ++ else ++ scheme = "riousbprint"; ++ ++ /* ++ * Extract the "remote printer key from the TXT record... ++ */ ++ ++ if ((pair = avahi_string_list_find (txt, "rp")) != NULL) ++ { ++ avahi_string_list_get_pair (pair, NULL, &value, &valueLen); ++ rp[0] = '/'; ++ memcpy (rp + 1, value, valueLen); ++ rp[valueLen + 1] = '\0'; ++ } ++ else ++ rp[0] = '\0'; ++ ++ /* ++ * Assemble the final device URI... ++ */ ++ ++ avahi_address_snprint (addr, AVAHI_ADDRESS_STR_MAX, address); ++ httpAssembleURI(HTTP_URI_CODING_ALL, poll_uribuf->uribuf.buffer, ++ poll_uribuf->uribuf.bufsize, scheme, NULL, ++ addr, port, rp); ++ DEBUG_printf(("avahi_resolve_uri_resolver_callback: Resolved URI is "%s"\n", ++ poll_uribuf->uribuf.buffer)); ++ avahi_simple_poll_quit (poll_uribuf->poll); ++} ++#endif /* HAVE_AVAHI */ ++ ++ + /* + * End of "$Id: http-support.c 9322 2010-10-01 22:40:38Z mike $". + */ +diff -up cups-1.4.5/scheduler/avahi.c.avahi cups-1.4.5/scheduler/avahi.c +--- cups-1.4.5/scheduler/avahi.c.avahi 2010-12-24 13:11:38.333341014 +0000 ++++ cups-1.4.5/scheduler/avahi.c 2010-12-24 13:11:38.333341014 +0000 +@@ -0,0 +1,441 @@ ++/* ++ * "$Id$" ++ * ++ * Avahi poll implementation for the CUPS scheduler. ++ * ++ * Copyright (C) 2010 Red Hat, Inc. ++ * Authors: ++ * Tim Waugh twaugh@redhat.com ++ * ++ * Distribution and use rights are outlined in the file "LICENSE.txt" ++ * "LICENSE" which should have been included with this file. If this ++ * file is missing or damaged, see the license at "http://www.cups.org/". ++ * ++ * Contents: ++ * ++ * watch_read_cb - Read callback for file descriptor ++ * watch_write_cb - Write callback for file descriptor ++ * watched_fd_add_select() - Call cupsdAddSelect() as needed ++ * watch_new() - Create a new file descriptor watch ++ * watch_free() - Free a file descriptor watch ++ * watch_update() - Update watched events for a file descriptor ++ * watch_get_events() - Get events that happened for a file descriptor ++ * timeout_cb() - Run a timed Avahi callback ++ * timeout_new() - Set a wakeup time ++ * timeout_update() - Update the expiration time for a timeout ++ * timeout_free() - Free a timeout ++ * compare_watched_fds() - Compare watched file descriptors for array sorting ++ * compare_timeouts() - Compare timeouts for array sorting ++ * avahi_cups_poll_new() - Create a new Avahi main loop object for CUPS ++ * avahi_cups_poll_free() - Free an Avahi main loop object for CUPS ++ * avahi_cups_poll_get() - Get the abstract poll API structure ++ */ ++ ++#include <config.h> ++ ++#ifdef HAVE_AVAHI /* Applies to entire file... */ ++ ++/* ++ * Include necessary headers... ++ */ ++ ++#include "cupsd.h" ++ ++#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) ++# include <malloc.h> ++#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ ++ ++#ifdef HAVE_AVAHI ++# include <avahi-common/timeval.h> ++#endif /* HAVE_AVAHI */ ++ ++ ++typedef struct ++{ ++ AvahiCupsPoll *cups_poll; ++ ++ int fd; ++ AvahiWatchEvent occurred; ++ cups_array_t *watches; ++} cupsd_watched_fd_t; ++ ++struct AvahiWatch ++{ ++ cupsd_watched_fd_t *watched_fd; ++ ++ AvahiWatchEvent events; ++ AvahiWatchCallback callback; ++ void *userdata; ++}; ++ ++struct AvahiTimeout ++{ ++ AvahiCupsPoll *cups_poll; ++ AvahiTimeoutCallback callback; ++ void *userdata; ++ cupsd_timeout_t *cupsd_timeout; ++}; ++ ++/* ++ * Local functions... ++ */ ++ ++static AvahiWatch * watch_new(const AvahiPoll *api, ++ int fd, ++ AvahiWatchEvent events, ++ AvahiWatchCallback callback, ++ void *userdata); ++static void watch_free(AvahiWatch *watch); ++static void watch_update(AvahiWatch *watch, ++ AvahiWatchEvent events); ++static AvahiWatchEvent watch_get_events(AvahiWatch *watch); ++static int compare_watches(AvahiWatch *p0, ++ AvahiWatch *p1); ++ ++ ++/* ++ * 'watch_read_cb' - Read callback for file descriptor ++ */ ++ ++static void ++watch_read_cb (void *userdata) ++{ ++ AvahiWatch *watch; ++ cupsd_watched_fd_t *watched_fd = userdata; ++ watched_fd->occurred |= AVAHI_WATCH_IN; ++ for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches); ++ watch; ++ watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches)) { ++ if (watch->events & watched_fd->occurred) { ++ (watch->callback) (watch, watched_fd->fd, ++ AVAHI_WATCH_IN, watch->userdata); ++ watched_fd->occurred &= ~AVAHI_WATCH_IN; ++ break; ++ } ++ } ++} ++ ++ ++/* ++ * 'watch_write_cb' - Write callback for file descriptor ++ */ ++ ++static void ++watch_write_cb (void *userdata) ++{ ++ AvahiWatch *watch; ++ cupsd_watched_fd_t *watched_fd = userdata; ++ watched_fd->occurred |= AVAHI_WATCH_OUT; ++ for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches); ++ watch; ++ watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches)) { ++ if (watch->events & watched_fd->occurred) { ++ (watch->callback) (watch, watched_fd->fd, ++ AVAHI_WATCH_OUT, watch->userdata); ++ watched_fd->occurred &= ~AVAHI_WATCH_OUT; ++ break; ++ } ++ } ++} ++ ++ ++/* ++ * 'watched_fd_add_select' - Call cupsdAddSelect() as needed ++ */ ++ ++static int /* O - Watches? */ ++watched_fd_add_select (cupsd_watched_fd_t *watched_fd) ++{ ++ AvahiWatch *watch; ++ cupsd_selfunc_t read_cb = NULL, write_cb = NULL; ++ ++ for (watch = (AvahiWatch *)cupsArrayFirst(watched_fd->watches); ++ watch; ++ watch = (AvahiWatch *)cupsArrayNext(watched_fd->watches)) { ++ if (watch->events & (AVAHI_WATCH_IN | ++ AVAHI_WATCH_ERR | ++ AVAHI_WATCH_HUP)) { ++ read_cb = (cupsd_selfunc_t)watch_read_cb; ++ if (write_cb != NULL) ++ break; ++ } ++ ++ if (watch->events & AVAHI_WATCH_OUT) { ++ write_cb = (cupsd_selfunc_t)watch_write_cb; ++ if (read_cb != NULL) ++ break; ++ } ++ } ++ ++ if (read_cb || write_cb) ++ cupsdAddSelect (watched_fd->fd, read_cb, write_cb, watched_fd); ++ else ++ cupsdRemoveSelect (watched_fd->fd); ++ ++ return (read_cb || write_cb); ++} ++ ++/* ++ * 'watch_new' - Create a new file descriptor watch ++ */ ++ ++static AvahiWatch * ++watch_new (const AvahiPoll *api, ++ int fd, ++ AvahiWatchEvent events, ++ AvahiWatchCallback callback, ++ void *userdata) ++{ ++ cupsd_watched_fd_t key, *watched_fd; ++ AvahiCupsPoll *cups_poll = api->userdata; ++ AvahiWatch *watch = malloc(sizeof(AvahiWatch)); ++ if (watch == NULL) ++ return (NULL); ++ ++ watch->events = events; ++ watch->callback = callback; ++ watch->userdata = userdata; ++ ++ key.fd = fd; ++ watched_fd = cupsArrayFind (cups_poll->watched_fds, &key); ++ if (watched_fd == NULL) { ++ watched_fd = malloc(sizeof(cupsd_watched_fd_t)); ++ if (watched_fd == NULL) ++ return (NULL); ++ ++ watched_fd->fd = fd; ++ watched_fd->occurred = 0; ++ watched_fd->watches = cupsArrayNew ((cups_array_func_t)compare_watches, ++ NULL); ++ } ++ ++ cupsArrayAdd(watched_fd->watches, watch); ++ watched_fd_add_select (watched_fd); ++ return (watch); ++} ++ ++ ++/* ++ * 'watch_free' - Free a file descriptor watch ++ */ ++ ++static void ++watch_free (AvahiWatch *watch) ++{ ++ cupsd_watched_fd_t *watched_fd = watch->watched_fd; ++ AvahiCupsPoll *cups_poll = watched_fd->cups_poll; ++ ++ cupsArrayRemove (watched_fd->watches, watch); ++ free (watch); ++ ++ if (!watched_fd_add_select (watched_fd)) { ++ /* No more watches */ ++ cupsArrayRemove (cups_poll->watched_fds, watched_fd); ++ free (watched_fd); ++ } ++} ++ ++ ++/* ++ * 'watch_update' - Update watched events for a file descriptor ++ */ ++ ++static void ++watch_update (AvahiWatch *watch, ++ AvahiWatchEvent events) ++{ ++ watch->events = events; ++ watched_fd_add_select (watch->watched_fd); ++} ++ ++ ++/* ++ * 'watch_get_events' - Get events that happened for a file descriptor ++ */ ++ ++static AvahiWatchEvent ++watch_get_events (AvahiWatch *watch) ++{ ++ return (watch->watched_fd->occurred); ++} ++ ++ ++/* ++ * 'compare_watches' - Compare watches for array sorting ++ */ ++ ++static int ++compare_watches (AvahiWatch *p0, ++ AvahiWatch *p1) ++{ ++ if (p0->watched_fd->fd < p1->watched_fd->fd) ++ return (-1); ++ ++ return ((p0->watched_fd->fd == p1->watched_fd->fd) ? 0 : 1); ++} ++ ++ ++/* ++ * 'timeout_cb()' - Run a timed Avahi callback ++ */ ++ ++static void ++timeout_cb (cupsd_timeout_t *cupsd_timeout, void *userdata) ++{ ++ AvahiTimeout *timeout = userdata; ++ (timeout->callback) (timeout, timeout->userdata); ++} ++ ++ ++/* ++ * 'timeout_new' - Set a wakeup time ++ */ ++ ++static AvahiTimeout * ++timeout_new (const AvahiPoll *api, ++ const struct timeval *tv, ++ AvahiTimeoutCallback callback, ++ void *userdata) ++{ ++ AvahiTimeout *timeout; ++ AvahiCupsPoll *cups_poll = api->userdata; ++ ++ timeout = malloc(sizeof(AvahiTimeout)); ++ if (timeout == NULL) ++ return (NULL); ++ ++ timeout->cups_poll = cups_poll; ++ timeout->callback = callback; ++ timeout->userdata = userdata; ++ timeout->cupsd_timeout = cupsdAddTimeout (tv, ++ (cupsd_timeoutfunc_t)timeout_cb, ++ timeout); ++ cupsArrayAdd (cups_poll->timeouts, timeout); ++ return (timeout); ++} ++ ++ ++/* ++ * 'timeout_update' - Update the expiration time for a timeout ++ */ ++ ++static void ++timeout_update (AvahiTimeout *timeout, ++ const struct timeval *tv) ++{ ++ cupsdUpdateTimeout (timeout->cupsd_timeout, tv); ++} ++ ++ ++/* ++ * ' timeout_free' - Free a timeout ++ */ ++ ++static void ++timeout_free (AvahiTimeout *timeout) ++{ ++ cupsArrayRemove (timeout->cups_poll->timeouts, timeout); ++ cupsdRemoveTimeout (timeout->cupsd_timeout); ++ free (timeout); ++} ++ ++ ++/* ++ * 'compare_watched_fds' - Compare watched file descriptors for array sorting ++ */ ++static int ++compare_watched_fds(cupsd_watched_fd_t *p0, ++ cupsd_watched_fd_t *p1) ++{ ++ if (p0->fd != p1->fd) ++ return (p0->fd < p1->fd ? -1 : 1); ++ ++ if (p0 == p1) ++ return (0); ++ ++ return (p0 < p1 ? -1 : 1); ++} ++ ++ ++/* ++ * 'compare_timeouts' - Compare timeouts for array sorting ++ */ ++static int ++compare_timeouts(AvahiTimeout *p0, ++ AvahiTimeout *p1) ++{ ++ /* ++ * Just compare pointers to make it a stable sort. ++ */ ++ ++ if (p0->cupsd_timeout < p1->cupsd_timeout) ++ return (-1); ++ return ((p0->cupsd_timeout == p1->cupsd_timeout) ? 0 : 1); ++} ++ ++ ++/* ++ * 'avahi_cups_poll_new' - Create a new Avahi main loop object for CUPS ++ */ ++ ++AvahiCupsPoll * ++avahi_cups_poll_new (void) ++{ ++ AvahiCupsPoll *cups_poll = malloc(sizeof(AvahiCupsPoll)); ++ if (cups_poll == NULL) ++ return (NULL); ++ ++ cups_poll->watched_fds = cupsArrayNew ((cups_array_func_t)compare_watched_fds, ++ NULL); ++ cups_poll->timeouts = cupsArrayNew ((cups_array_func_t)compare_timeouts, ++ NULL); ++ ++ cups_poll->api.userdata = cups_poll; ++ cups_poll->api.watch_new = watch_new; ++ cups_poll->api.watch_free = watch_free; ++ cups_poll->api.watch_update = watch_update; ++ cups_poll->api.watch_get_events = watch_get_events; ++ ++ cups_poll->api.timeout_new = timeout_new; ++ cups_poll->api.timeout_update = timeout_update; ++ cups_poll->api.timeout_free = timeout_free; ++ ++ return (cups_poll); ++} ++ ++ ++/* ++ * 'avahi_cups_poll_free' - Free an Avahi main loop object for CUPS ++ */ ++void ++avahi_cups_poll_free (AvahiCupsPoll *cups_poll) ++{ ++ cupsd_watched_fd_t *watched_fd; ++ ++ for (watched_fd = (cupsd_watched_fd_t*)cupsArrayFirst(cups_poll->watched_fds); ++ watched_fd; ++ watched_fd = (cupsd_watched_fd_t*)cupsArrayNext(cups_poll->watched_fds)){ ++ cupsArrayClear (watched_fd->watches); ++ } ++ ++ cupsArrayClear (cups_poll->watched_fds); ++ cupsArrayClear (cups_poll->timeouts); ++} ++ ++ ++/* ++ * 'avahi_cups_poll_get' - Get the abstract poll API structure ++ */ ++ ++const AvahiPoll * ++avahi_cups_poll_get (AvahiCupsPoll *cups_poll) ++{ ++ return (&cups_poll->api); ++} ++ ++ ++#endif /* HAVE_AVAHI ... from top of file */ ++ ++/* ++ * End of "$Id$". ++ */ +diff -up cups-1.4.5/scheduler/avahi.h.avahi cups-1.4.5/scheduler/avahi.h +--- cups-1.4.5/scheduler/avahi.h.avahi 2010-12-24 13:11:38.334340988 +0000 ++++ cups-1.4.5/scheduler/avahi.h 2010-12-24 13:11:38.334340988 +0000 +@@ -0,0 +1,49 @@ ++/* ++ * "$Id$" ++ * ++ * Avahi poll implementation for the CUPS scheduler. ++ * ++ * Copyright (C) 2010 Red Hat, Inc. ++ * Authors: ++ * Tim Waugh twaugh@redhat.com ++ * ++ * Distribution and use rights are outlined in the file "LICENSE.txt" ++ * which should have been included with this file. If this file is ++ * file is missing or damaged, see the license at "http://www.cups.org/". ++ */ ++ ++#include <config.h> ++ ++#ifdef HAVE_AVAHI ++# include <avahi-client/client.h> ++# include <avahi-client/publish.h> ++#endif /* HAVE_AVAHI */ ++ ++#ifdef HAVE_AUTHORIZATION_H ++# include <Security/Authorization.h> ++#endif /* HAVE_AUTHORIZATION_H */ ++ ++ ++#ifdef HAVE_AVAHI ++typedef struct ++{ ++ AvahiPoll api; ++ cups_array_t *watched_fds; ++ cups_array_t *timeouts; ++} AvahiCupsPoll; ++#endif /* HAVE_AVAHI */ ++ ++/* ++ * Prototypes... ++ */ ++ ++#ifdef HAVE_AVAHI ++extern AvahiCupsPoll * avahi_cups_poll_new(void); ++extern void avahi_cups_poll_free(AvahiCupsPoll *cups_poll); ++extern const AvahiPoll *avahi_cups_poll_get(AvahiCupsPoll *cups_poll); ++#endif /* HAVE_AVAHI */ ++ ++ ++/* ++ * End of "$Id$". ++ */ +diff -up cups-1.4.5/scheduler/cupsd.h.avahi cups-1.4.5/scheduler/cupsd.h +--- cups-1.4.5/scheduler/cupsd.h.avahi 2010-09-21 23:34:57.000000000 +0100 ++++ cups-1.4.5/scheduler/cupsd.h 2010-12-24 13:11:38.335340961 +0000 +@@ -147,6 +147,15 @@ extern const char *cups_hstrerror(int); + + typedef void (*cupsd_selfunc_t)(void *data); + ++#ifdef HAVE_AVAHI ++/* ++ * Timeout callback function type... ++ */ ++ ++typedef struct _cupsd_timeout_s cupsd_timeout_t; ++typedef void (*cupsd_timeoutfunc_t)(cupsd_timeout_t *timeout, void *data); ++#endif /* HAVE_AVAHI */ ++ + + /* + * Globals... +@@ -188,6 +197,9 @@ VAR PSQUpdateQuotaProcPtr PSQUpdateQuota + /* Apple PrintService quota function */ + #endif /* __APPLE__ && HAVE_DLFCN_H */ + ++#ifdef HAVE_AVAHI ++VAR cups_array_t *Timeouts; /* Timed callbacks for main loop */ ++#endif /* HAVE_AVAHI */ + + + +@@ -240,6 +252,18 @@ extern void cupsdRemoveSelect(int fd); + extern void cupsdStartSelect(void); + extern void cupsdStopSelect(void); + ++#ifdef HAVE_AVAHI ++extern void cupsdInitTimeouts(void); ++extern cupsd_timeout_t *cupsdAddTimeout (const struct timeval *tv, ++ cupsd_timeoutfunc_t cb, ++ void *data); ++extern cupsd_timeout_t *cupsdNextTimeout (long *delay); ++extern void cupsdRunTimeout (cupsd_timeout_t *timeout); ++extern void cupsdUpdateTimeout (cupsd_timeout_t *timeout, ++ const struct timeval *tv); ++extern void cupsdRemoveTimeout (cupsd_timeout_t *timeout); ++#endif /* HAVE_AVAHI */ ++ + extern int cupsdRemoveFile(const char *filename); + + +diff -up cups-1.4.5/scheduler/dirsvc.c.avahi cups-1.4.5/scheduler/dirsvc.c +--- cups-1.4.5/scheduler/dirsvc.c.avahi 2010-12-24 13:11:33.679463507 +0000 ++++ cups-1.4.5/scheduler/dirsvc.c 2010-12-24 13:11:38.343340751 +0000 +@@ -99,6 +99,13 @@ + #endif /* HAVE_DNSSD */ + + ++#ifdef HAVE_DNSSD ++typedef char *cupsd_txt_record_t; ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++typedef AvahiStringList *cupsd_txt_record_t; ++#endif /* HAVE_AVAHI */ ++ + /* + * Local functions... + */ +@@ -159,15 +166,20 @@ static void update_polling(void); + static void update_smb(int onoff); + + ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++static cupsd_txt_record_t dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p, ++ int for_lpd); ++static void dnssdDeregisterPrinter(cupsd_printer_t *p); ++static int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b); ++static void dnssdRegisterPrinter(cupsd_printer_t *p); ++static void dnssdStop(void); ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ ++ + #ifdef HAVE_DNSSD + # ifdef HAVE_COREFOUNDATION + static void dnssdAddAlias(const void *key, const void *value, + void *context); + # endif /* HAVE_COREFOUNDATION */ +-static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p, +- int for_lpd); +-static int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b); +-static void dnssdDeregisterPrinter(cupsd_printer_t *p); + static char *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2], + int count); + static void dnssdRegisterCallback(DNSServiceRef sdRef, +@@ -175,11 +187,20 @@ static void dnssdRegisterCallback(DNSSer + DNSServiceErrorType errorCode, + const char *name, const char *regtype, + const char *domain, void *context); +-static void dnssdRegisterPrinter(cupsd_printer_t *p); +-static void dnssdStop(void); + static void dnssdUpdate(void); + #endif /* HAVE_DNSSD */ + ++#ifdef HAVE_AVAHI ++static AvahiStringList *avahiPackTxtRecord(char *keyvalue[][2], ++ int count); ++static void avahi_entry_group_cb (AvahiEntryGroup *group, ++ AvahiEntryGroupState state, ++ void *userdata); ++static void avahi_client_cb (AvahiClient *client, ++ AvahiClientState state, ++ void *userdata); ++#endif /* HAVE_AVAHI */ ++ + #ifdef HAVE_LDAP + static const char * const ldap_attrs[] =/* CUPS LDAP attributes */ + { +@@ -283,10 +304,10 @@ cupsdDeregisterPrinter( + ldap_dereg_printer(p); + #endif /* HAVE_LDAP */ + +-#ifdef HAVE_DNSSD +- if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++ if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD)) + dnssdDeregisterPrinter(p); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + } + + +@@ -694,10 +715,10 @@ cupsdRegisterPrinter(cupsd_printer_t *p) + slpRegisterPrinter(p); */ + #endif /* HAVE_LIBSLP */ + +-#ifdef HAVE_DNSSD +- if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++ if ((BrowseLocalProtocols & BROWSE_DNSSD)) + dnssdRegisterPrinter(p); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + } + + +@@ -1535,13 +1556,16 @@ cupsdStartBrowsing(void) + else + BrowseSocket = -1; + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_DNSSD) + { ++#ifdef HAVE_DNSSD + DNSServiceErrorType error; /* Error from service creation */ ++#endif /* HAVE_DNSSD */ + cupsd_listener_t *lis; /* Current listening socket */ + + ++#ifdef HAVE_DNSSD + /* + * First create a "master" connection for all registrations... + */ +@@ -1566,6 +1590,7 @@ cupsdStartBrowsing(void) + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + + cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL); ++#endif /* HAVE_DNSSD */ + + /* + * Then get the port we use for registrations. If we are not listening +@@ -1607,9 +1632,20 @@ cupsdStartBrowsing(void) + */ + + cupsdUpdateDNSSDName(); ++#ifdef HAVE_DNSSD + } +- } + #endif /* HAVE_DNSSD */ ++ } ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ ++ ++#ifdef HAVE_AVAHI ++ if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_DNSSD) ++ { ++ AvahiCupsPollHandle = avahi_cups_poll_new (); ++ avahi_client_new (avahi_cups_poll_get (AvahiCupsPollHandle), ++ 0, avahi_client_cb, NULL, NULL); ++ } ++#endif /* HAVE_AVAHI */ + + #ifdef HAVE_LIBSLP + if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) +@@ -1835,10 +1871,10 @@ cupsdStopBrowsing(void) + BrowseSocket = -1; + } + +-#ifdef HAVE_DNSSD +- if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef) ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++ if ((BrowseLocalProtocols & BROWSE_DNSSD)) + dnssdStop(); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + + #ifdef HAVE_LIBSLP + if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) && +@@ -1903,7 +1939,7 @@ cupsdStopPolling(void) + } + + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + /* + * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing... + */ +@@ -1911,7 +1947,12 @@ cupsdStopPolling(void) + void + cupsdUpdateDNSSDName(void) + { ++#ifdef HAVE_DNSSD + DNSServiceErrorType error; /* Error from service creation */ ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ int ret; /* Error from service creation */ ++#endif /* HAVE_AVAHI */ + char webif[1024]; /* Web interface share name */ + #ifdef HAVE_COREFOUNDATION_H + SCDynamicStoreRef sc; /* Context for dynamic store */ +@@ -2043,6 +2084,7 @@ cupsdUpdateDNSSDName(void) + else + strlcpy(webif, "CUPS Web Interface", sizeof(webif)); + ++#ifdef HAVE_DNSSD + if (WebIFRef) + DNSServiceRefDeallocate(WebIFRef); + +@@ -2055,6 +2097,42 @@ cupsdUpdateDNSSDName(void) + NULL)) != kDNSServiceErr_NoError) + cupsdLogMessage(CUPSD_LOG_ERROR, + "DNS-SD web interface registration failed: %d", error); ++#endif /* HAVE_DNSSD */ ++ ++#ifdef HAVE_AVAHI ++ if (!AvahiCupsClient) ++ /* ++ * Client not yet running. ++ */ ++ return; ++ ++ if (AvahiWebIFGroup) ++ avahi_entry_group_reset (AvahiWebIFGroup); ++ else ++ AvahiWebIFGroup = avahi_entry_group_new (AvahiCupsClient, ++ avahi_entry_group_cb, ++ NULL); ++ ++ if (AvahiWebIFGroup) ++ { ++ ret = avahi_entry_group_add_service (AvahiWebIFGroup, ++ AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ 0, /* flags */ ++ webif, /* name */ ++ "_http._tcp", /* type */ ++ NULL, /* domain */ ++ NULL, /* host */ ++ htons(DNSSDPort), /* port */ ++ "path=/", NULL); ++ if (ret == 0) ++ ret = avahi_entry_group_commit (AvahiWebIFGroup); ++ ++ if (ret != 0) ++ cupsdLogMessage (CUPSD_LOG_ERROR, ++ "Avahi web interface registration failed: %d", ret); ++ } ++#endif /* HAVE_AVAHI */ + } + } + #endif /* HAVE_DNSSD */ +@@ -2300,162 +2378,7 @@ dequote(char *d, /* I - Destinat + } + + +-#ifdef HAVE_DNSSD +-# ifdef HAVE_COREFOUNDATION +-/* +- * 'dnssdAddAlias()' - Add a DNS-SD alias name. +- */ +- +-static void +-dnssdAddAlias(const void *key, /* I - Key */ +- const void *value, /* I - Value (domain) */ +- void *context) /* I - Unused */ +-{ +- char valueStr[1024], /* Domain string */ +- hostname[1024]; /* Complete hostname */ +- +- +- (void)context; +- +- if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() && +- CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr), +- kCFStringEncodingUTF8)) +- { +- snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr); +- if (!DNSSDAlias) +- DNSSDAlias = cupsArrayNew(NULL, NULL); +- +- cupsdAddAlias(DNSSDAlias, hostname); +- cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s", +- hostname); +- } +- else +- cupsdLogMessage(CUPSD_LOG_ERROR, +- "Bad Back to My Mac domain in dynamic store!"); +-} +-# endif /* HAVE_COREFOUNDATION */ +- +- +-/* +- * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info. +- */ +- +-static char * /* O - TXT record */ +-dnssdBuildTxtRecord( +- int *txt_len, /* O - TXT record length */ +- cupsd_printer_t *p, /* I - Printer information */ +- int for_lpd) /* I - 1 = LPD, 0 = IPP */ +-{ +- int i; /* Looping var */ +- char adminurl_str[256], /* URL for th admin page */ +- type_str[32], /* Type to string buffer */ +- state_str[32], /* State to string buffer */ +- rp_str[1024], /* Queue name string buffer */ +- air_str[1024], /* auth-info-required string buffer */ +- *keyvalue[32][2]; /* Table of key/value pairs */ +- +- +- /* +- * Load up the key value pairs... +- */ +- +- i = 0; +- +- keyvalue[i ][0] = "txtvers"; +- keyvalue[i++][1] = "1"; +- +- keyvalue[i ][0] = "qtotal"; +- keyvalue[i++][1] = "1"; +- +- keyvalue[i ][0] = "rp"; +- keyvalue[i++][1] = rp_str; +- if (for_lpd) +- strlcpy(rp_str, p->name, sizeof(rp_str)); +- else +- snprintf(rp_str, sizeof(rp_str), "%s/%s", +- (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); +- +- keyvalue[i ][0] = "ty"; +- keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown"; +- +- httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), +- "http", NULL, DNSSDHostName, DNSSDPort, "/%s/%s", +- (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", +- p->name); +- keyvalue[i ][0] = "adminurl"; +- keyvalue[i++][1] = adminurl_str; +- +- keyvalue[i ][0] = "note"; +- keyvalue[i++][1] = p->location ? p->location : ""; +- +- keyvalue[i ][0] = "priority"; +- keyvalue[i++][1] = for_lpd ? "100" : "0"; +- +- keyvalue[i ][0] = "product"; +- keyvalue[i++][1] = p->product ? p->product : "Unknown"; +- +- snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); +- snprintf(state_str, sizeof(state_str), "%d", p->state); +- +- keyvalue[i ][0] = "printer-state"; +- keyvalue[i++][1] = state_str; +- +- keyvalue[i ][0] = "printer-type"; +- keyvalue[i++][1] = type_str; +- +- keyvalue[i ][0] = "Transparent"; +- keyvalue[i++][1] = "T"; +- +- keyvalue[i ][0] = "Binary"; +- keyvalue[i++][1] = "T"; +- +- keyvalue[i ][0] = "Fax"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F"; +- +- keyvalue[i ][0] = "Color"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F"; +- +- keyvalue[i ][0] = "Duplex"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F"; +- +- keyvalue[i ][0] = "Staple"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F"; +- +- keyvalue[i ][0] = "Copies"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F"; +- +- keyvalue[i ][0] = "Collate"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F"; +- +- keyvalue[i ][0] = "Punch"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F"; +- +- keyvalue[i ][0] = "Bind"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F"; +- +- keyvalue[i ][0] = "Sort"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F"; +- +- keyvalue[i ][0] = "Scan"; +- keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F"; +- +- keyvalue[i ][0] = "pdl"; +- keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript"; +- +- if (get_auth_info_required(p, air_str, sizeof(air_str))) +- { +- keyvalue[i ][0] = "air"; +- keyvalue[i++][1] = air_str; +- } +- +- /* +- * Then pack them into a proper txt record... +- */ +- +- return (dnssdPackTxtRecord(txt_len, keyvalue, i)); +-} +- +- ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + /* + * 'dnssdComparePrinters()' - Compare the registered names of two printers. + */ +@@ -2479,6 +2402,10 @@ dnssdDeregisterPrinter( + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name); + ++#ifdef HAVE_DNSSD ++ if (!DNSSDRef) ++ return; ++ + /* + * Closing the socket deregisters the service + */ +@@ -2514,6 +2441,23 @@ dnssdDeregisterPrinter( + free(p->printer_txt); + p->printer_txt = NULL; + } ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ if (p->avahi_group) ++ { ++ avahi_entry_group_reset (p->avahi_group); ++ avahi_entry_group_free (p->avahi_group); ++ p->avahi_group = NULL; ++ ++ if (p->ipp_txt) ++ avahi_string_list_free (p->ipp_txt); ++ ++ if (p->printer_txt) ++ avahi_string_list_free (p->printer_txt); ++ ++ p->ipp_txt = p->printer_txt = NULL; ++ } ++#endif /* HAVE_AVAHI */ + + /* + * Remove the printer from the array of DNS-SD printers, then clear the +@@ -2526,140 +2470,53 @@ dnssdDeregisterPrinter( + + + /* +- * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the +- * TXT record format. ++ * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer ++ * or update the broadcast contents. + */ + +-static char * /* O - TXT record */ +-dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */ +- char *keyvalue[][2], /* I - Table of key value pairs */ +- int count) /* I - Items in table */ ++static void ++dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ + { +- int i; /* Looping var */ +- int length; /* Length of TXT record */ +- int length2; /* Length of value */ +- char *txtRecord; /* TXT record buffer */ +- char *cursor; /* Looping pointer */ ++#ifdef HAVE_DNSSD ++ DNSServiceErrorType se; /* dnssd errors */ ++ char *ipp_txt, /* IPP TXT record buffer */ ++ *printer_txt, /* LPD TXT record buffer */ ++ *nameptr; /* Pointer into name */ ++ int ipp_len, /* IPP TXT record length */ ++ printer_len; /* LPD TXT record length */ ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ int ret; /* Error code */ ++ AvahiStringList *ipp_txt, /* IPP TXT record list */ ++ *printer_txt; /* LPD TXT record buffer */ ++#endif /* HAVE_AVAHI */ ++ char name[1024]; /* Service name */ ++ const char *regtype; /* Registration type */ + + +- /* +- * Calculate the buffer size +- */ ++#ifdef HAVE_DNSSD ++ if (!DNSSDRef) ++ return; + +- for (length = i = 0; i < count; i++) +- length += 1 + strlen(keyvalue[i][0]) + +- (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0); ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, ++ !p->ipp_ref ? "new" : "update"); ++ ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, ++ !p->avahi_group ? "new" : "update"); ++#endif /* HAVE_AVAHI */ + + /* +- * Allocate and fill it ++ * If per-printer sharing was just disabled make sure we're not ++ * registered before returning. + */ + +- txtRecord = malloc(length); +- if (txtRecord) ++ if (!p->shared) + { +- *txt_len = length; +- +- for (cursor = txtRecord, i = 0; i < count; i++) +- { +- /* +- * Drop in the p-string style length byte followed by the data +- */ +- +- length = strlen(keyvalue[i][0]); +- length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0; +- +- *cursor++ = (unsigned char)(length + length2); +- +- memcpy(cursor, keyvalue[i][0], length); +- cursor += length; +- +- if (length2) +- { +- length2 --; +- *cursor++ = '='; +- memcpy(cursor, keyvalue[i][1], length2); +- cursor += length2; +- } +- } +- } +- +- return (txtRecord); +-} +- +- +-/* +- * 'dnssdRegisterCallback()' - DNSServiceRegister callback. +- */ +- +-static void +-dnssdRegisterCallback( +- DNSServiceRef sdRef, /* I - DNS Service reference */ +- DNSServiceFlags flags, /* I - Reserved for future use */ +- DNSServiceErrorType errorCode, /* I - Error code */ +- const char *name, /* I - Service name */ +- const char *regtype, /* I - Service type */ +- const char *domain, /* I - Domain. ".local" for now */ +- void *context) /* I - User-defined context */ +-{ +- cupsd_printer_t *p = (cupsd_printer_t *)context; +- /* Current printer */ +- +- +- cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)", +- name, regtype, p ? p->name : "Web Interface", +- p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); +- +- if (errorCode) +- { +- cupsdLogMessage(CUPSD_LOG_ERROR, +- "DNSServiceRegister failed with error %d", (int)errorCode); +- return; +- } +- else if (p && (!p->reg_name || strcasecmp(name, p->reg_name))) +- { +- cupsdLogMessage(CUPSD_LOG_INFO, "Using service name "%s" for "%s"", +- name, p->name); +- +- cupsArrayRemove(DNSSDPrinters, p); +- cupsdSetString(&p->reg_name, name); +- cupsArrayAdd(DNSSDPrinters, p); +- +- LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED; +- } +-} +- +- +-/* +- * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer +- * or update the broadcast contents. +- */ +- +-static void +-dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ +-{ +- DNSServiceErrorType se; /* dnssd errors */ +- char *ipp_txt, /* IPP TXT record buffer */ +- *printer_txt, /* LPD TXT record buffer */ +- name[1024], /* Service name */ +- *nameptr; /* Pointer into name */ +- int ipp_len, /* IPP TXT record length */ +- printer_len; /* LPD TXT record length */ +- const char *regtype; /* Registration type */ +- +- +- cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, +- !p->ipp_ref ? "new" : "update"); +- +- /* +- * If per-printer sharing was just disabled make sure we're not +- * registered before returning. +- */ +- +- if (!p->shared) +- { +- dnssdDeregisterPrinter(p); +- return; +- } ++ dnssdDeregisterPrinter(p); ++ return; ++ } + + /* + * The registered name takes the form of "<printer-info> @ <computer name>"... +@@ -2694,6 +2551,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p) + * Register IPP and (optionally) LPD... + */ + ++#ifdef HAVE_DNSSD + ipp_len = 0; /* anti-compiler-warning-code */ + ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0); + +@@ -2860,6 +2718,140 @@ dnssdRegisterPrinter(cupsd_printer_t *p) + if (printer_txt) + free(printer_txt); + } ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ if (!AvahiCupsClient) ++ /* ++ * Client not running yet. The client callback will call us again later. ++ */ ++ return; ++ ++ ipp_txt = dnssdBuildTxtRecord(NULL, p, 0); ++ printer_txt = dnssdBuildTxtRecord(NULL, p, 1); ++ regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : "_ipp._tcp"; ++ ++ if (p->avahi_group && p->ipp_txt && ipp_txt && ++ !avahi_string_list_equal (p->ipp_txt, ipp_txt)) ++ { ++ /* ++ * Update the existing registration... ++ */ ++ ++ avahi_string_list_free (p->ipp_txt); ++ ++ if (p->printer_txt) ++ avahi_string_list_free (p->printer_txt); ++ ++ ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group, ++ AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ 0, name, regtype, NULL, ++ ipp_txt); ++ if (ret < 0) ++ goto update_failed; ++ ++ p->ipp_txt = ipp_txt; ++ ipp_txt = NULL; ++ ++ if (BrowseLocalProtocols & BROWSE_LPD) ++ { ++ ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group, ++ AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ 0, name, ++ "_printer._tcp", NULL, ++ printer_txt); ++ ++ if (ret < 0) ++ goto update_failed; ++ ++ p->printer_txt = printer_txt; ++ printer_txt = NULL; ++ } ++ ++ ret = avahi_entry_group_commit (p->avahi_group); ++ if (ret < 0) ++ { ++ update_failed: ++ cupsdLogMessage (CUPSD_LOG_ERROR, ++ "Failed to update TXT record for %s: %d", ++ name, ret); ++ avahi_entry_group_reset (p->avahi_group); ++ avahi_entry_group_free (p->avahi_group); ++ p->avahi_group = NULL; ++ ipp_txt = p->ipp_txt; ++ p->ipp_txt = NULL; ++ } ++ } ++ ++ if (!p->avahi_group) ++ { ++ /* ++ * Initial registration. Use the _fax subtype for fax queues... ++ */ ++ ++ p->avahi_group = avahi_entry_group_new (AvahiCupsClient, ++ avahi_entry_group_cb, ++ p); ++ ++ cupsdLogMessage(CUPSD_LOG_DEBUG, ++ "Registering Avahi printer %s with name "%s" and " ++ "type "%s"", p->name, name, regtype); ++ ++ ret = avahi_entry_group_add_service_strlst (p->avahi_group, ++ AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ 0, name, regtype, NULL, NULL, ++ htons(DNSSDPort), ++ ipp_txt); ++ if (ret < 0) ++ goto add_failed; ++ ++ p->ipp_txt = ipp_txt; ++ ipp_txt = NULL; ++ ++ if (BrowseLocalProtocols & BROWSE_LPD) ++ { ++ cupsdLogMessage(CUPSD_LOG_DEBUG, ++ "Registering Avahi printer %s with name "%s" and " ++ "type "_printer._tcp"", p->name, name); ++ ++ ret = avahi_entry_group_add_service_strlst (p->avahi_group, ++ AVAHI_IF_UNSPEC, ++ AVAHI_PROTO_UNSPEC, ++ 0, name, ++ "_printer._tcp", NULL, NULL, ++ htons(515), ++ printer_txt); ++ if (ret < 0) ++ goto add_failed; ++ ++ p->printer_txt = printer_txt; ++ printer_txt = NULL; ++ } ++ ++ ret = avahi_entry_group_commit (p->avahi_group); ++ ++ if (ret < 0) ++ { ++ add_failed: ++ cupsdLogMessage (CUPSD_LOG_ERROR, ++ "Failed to add Avahi entry for %s: %d", ++ name, ret); ++ avahi_entry_group_reset (p->avahi_group); ++ avahi_entry_group_free (p->avahi_group); ++ p->avahi_group = NULL; ++ ipp_txt = p->ipp_txt; ++ p->ipp_txt = NULL; ++ } ++ } ++ ++ if (ipp_txt) ++ avahi_string_list_free (ipp_txt); ++ ++ if (printer_txt) ++ avahi_string_list_free (printer_txt); ++#endif /* HAVE_AVAHI */ + } + + +@@ -2872,6 +2864,10 @@ dnssdStop(void) + { + cupsd_printer_t *p; /* Current printer */ + ++#ifdef HAVE_DNSSD ++ if (!DNSSDRef) ++ return; ++#endif /* HAVE_DNSSD */ + + /* + * De-register the individual printers +@@ -2882,6 +2878,7 @@ dnssdStop(void) + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + dnssdDeregisterPrinter(p); + ++#ifdef HAVE_DNSSD + /* + * Shutdown the rest of the service refs... + */ +@@ -2902,6 +2899,7 @@ dnssdStop(void) + + DNSServiceRefDeallocate(DNSSDRef); + DNSSDRef = NULL; ++#endif /* HAVE_DNSSD */ + + cupsArrayDelete(DNSSDPrinters); + DNSSDPrinters = NULL; +@@ -2911,6 +2909,272 @@ dnssdStop(void) + + + /* ++ * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info. ++ */ ++ ++static cupsd_txt_record_t /* O - TXT record */ ++dnssdBuildTxtRecord( ++ int *txt_len, /* O - TXT record length */ ++ cupsd_printer_t *p, /* I - Printer information */ ++ int for_lpd) /* I - 1 = LPD, 0 = IPP */ ++{ ++ int i; /* Looping var */ ++ char adminurl_str[256], /* URL for th admin page */ ++ type_str[32], /* Type to string buffer */ ++ state_str[32], /* State to string buffer */ ++ rp_str[1024], /* Queue name string buffer */ ++ air_str[1024], /* auth-info-required string buffer */ ++ *keyvalue[32][2]; /* Table of key/value pairs */ ++ ++ ++ /* ++ * Load up the key value pairs... ++ */ ++ ++ i = 0; ++ ++ keyvalue[i ][0] = "txtvers"; ++ keyvalue[i++][1] = "1"; ++ ++ keyvalue[i ][0] = "qtotal"; ++ keyvalue[i++][1] = "1"; ++ ++ keyvalue[i ][0] = "rp"; ++ keyvalue[i++][1] = rp_str; ++ if (for_lpd) ++ strlcpy(rp_str, p->name, sizeof(rp_str)); ++ else ++ snprintf(rp_str, sizeof(rp_str), "%s/%s", ++ (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name); ++ ++ keyvalue[i ][0] = "ty"; ++ keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown"; ++ ++ httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str), ++ "http", NULL, DNSSDHostName, DNSSDPort, "/%s/%s", ++ (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", ++ p->name); ++ keyvalue[i ][0] = "adminurl"; ++ keyvalue[i++][1] = adminurl_str; ++ ++ keyvalue[i ][0] = "note"; ++ keyvalue[i++][1] = p->location ? p->location : ""; ++ ++ keyvalue[i ][0] = "priority"; ++ keyvalue[i++][1] = for_lpd ? "100" : "0"; ++ ++ keyvalue[i ][0] = "product"; ++ keyvalue[i++][1] = p->product ? p->product : "Unknown"; ++ ++ snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); ++ snprintf(state_str, sizeof(state_str), "%d", p->state); ++ ++ keyvalue[i ][0] = "printer-state"; ++ keyvalue[i++][1] = state_str; ++ ++ keyvalue[i ][0] = "printer-type"; ++ keyvalue[i++][1] = type_str; ++ ++ keyvalue[i ][0] = "Transparent"; ++ keyvalue[i++][1] = "T"; ++ ++ keyvalue[i ][0] = "Binary"; ++ keyvalue[i++][1] = "T"; ++ ++ keyvalue[i ][0] = "Fax"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Color"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Duplex"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Staple"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Copies"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Collate"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Punch"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Bind"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Sort"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "Scan"; ++ keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F"; ++ ++ keyvalue[i ][0] = "pdl"; ++ keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript"; ++ ++ if (get_auth_info_required(p, air_str, sizeof(air_str))) ++ { ++ keyvalue[i ][0] = "air"; ++ keyvalue[i++][1] = air_str; ++ } ++ ++ /* ++ * Then pack them into a proper txt record... ++ */ ++ ++#ifdef HAVE_DNSSD ++ return (dnssdPackTxtRecord(txt_len, keyvalue, i)); ++#endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ return (avahiPackTxtRecord(keyvalue, i)); ++#endif /* HAVE_AVAHI */ ++} ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ ++ ++ ++#ifdef HAVE_DNSSD ++# ifdef HAVE_COREFOUNDATION ++/* ++ * 'dnssdAddAlias()' - Add a DNS-SD alias name. ++ */ ++ ++static void ++dnssdAddAlias(const void *key, /* I - Key */ ++ const void *value, /* I - Value (domain) */ ++ void *context) /* I - Unused */ ++{ ++ char valueStr[1024], /* Domain string */ ++ hostname[1024]; /* Complete hostname */ ++ ++ ++ (void)context; ++ ++ if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() && ++ CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr), ++ kCFStringEncodingUTF8)) ++ { ++ snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr); ++ if (!DNSSDAlias) ++ DNSSDAlias = cupsArrayNew(NULL, NULL); ++ ++ cupsdAddAlias(DNSSDAlias, hostname); ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s", ++ hostname); ++ } ++ else ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "Bad Back to My Mac domain in dynamic store!"); ++} ++# endif /* HAVE_COREFOUNDATION */ ++ ++ ++/* ++ * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the ++ * TXT record format. ++ */ ++ ++static char * /* O - TXT record */ ++dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */ ++ char *keyvalue[][2], /* I - Table of key value pairs */ ++ int count) /* I - Items in table */ ++{ ++ int i; /* Looping var */ ++ int length; /* Length of TXT record */ ++ int length2; /* Length of value */ ++ char *txtRecord; /* TXT record buffer */ ++ char *cursor; /* Looping pointer */ ++ ++ ++ /* ++ * Calculate the buffer size ++ */ ++ ++ for (length = i = 0; i < count; i++) ++ length += 1 + strlen(keyvalue[i][0]) + ++ (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0); ++ ++ /* ++ * Allocate and fill it ++ */ ++ ++ txtRecord = malloc(length); ++ if (txtRecord) ++ { ++ *txt_len = length; ++ ++ for (cursor = txtRecord, i = 0; i < count; i++) ++ { ++ /* ++ * Drop in the p-string style length byte followed by the data ++ */ ++ ++ length = strlen(keyvalue[i][0]); ++ length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0; ++ ++ *cursor++ = (unsigned char)(length + length2); ++ ++ memcpy(cursor, keyvalue[i][0], length); ++ cursor += length; ++ ++ if (length2) ++ { ++ length2 --; ++ *cursor++ = '='; ++ memcpy(cursor, keyvalue[i][1], length2); ++ cursor += length2; ++ } ++ } ++ } ++ ++ return (txtRecord); ++} ++ ++ ++/* ++ * 'dnssdRegisterCallback()' - DNSServiceRegister callback. ++ */ ++ ++static void ++dnssdRegisterCallback( ++ DNSServiceRef sdRef, /* I - DNS Service reference */ ++ DNSServiceFlags flags, /* I - Reserved for future use */ ++ DNSServiceErrorType errorCode, /* I - Error code */ ++ const char *name, /* I - Service name */ ++ const char *regtype, /* I - Service type */ ++ const char *domain, /* I - Domain. ".local" for now */ ++ void *context) /* I - User-defined context */ ++{ ++ cupsd_printer_t *p = (cupsd_printer_t *)context; ++ /* Current printer */ ++ ++ ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)", ++ name, regtype, p ? p->name : "Web Interface", ++ p ? (p->reg_name ? p->reg_name : "(null)") : "NA"); ++ ++ if (errorCode) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "DNSServiceRegister failed with error %d", (int)errorCode); ++ return; ++ } ++ else if (p && (!p->reg_name || strcasecmp(name, p->reg_name))) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "Using service name "%s" for "%s"", ++ name, p->name); ++ ++ cupsArrayRemove(DNSSDPrinters, p); ++ cupsdSetString(&p->reg_name, name); ++ cupsArrayAdd(DNSSDPrinters, p); ++ ++ LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED; ++ } ++} ++ ++ ++/* + * 'dnssdUpdate()' - Handle DNS-SD queries. + */ + +@@ -2931,6 +3195,126 @@ dnssdUpdate(void) + #endif /* HAVE_DNSSD */ + + ++#ifdef HAVE_AVAHI ++/* ++ * 'avahiPackTxtRecord()' - Pack an array of key/value pairs into an ++ * AvahiStringList. ++ */ ++ ++static AvahiStringList * /* O - new string list */ ++avahiPackTxtRecord(char *keyvalue[][2], /* I - Table of key value pairs */ ++ int count) /* I - Items in table */ ++{ ++ AvahiStringList *strlst = NULL; ++ char **elements; ++ size_t len; ++ int i; ++ ++ elements = malloc ((1 + count) * sizeof (char *)); ++ if (!elements) ++ goto cleanup; ++ ++ for (i = 0; i < count; i++) ++ { ++ len = (1 + strlen (keyvalue[i][0]) + ++ (keyvalue[i][1] ? 1 + strlen (keyvalue[i][1]) : 1)); ++ elements[i] = malloc (len * sizeof (char)); ++ if (!elements[i]) ++ goto cleanup; ++ ++ snprintf (elements[i], len, "%s=%s", keyvalue[i][0], keyvalue[i][1]); ++ } ++ ++ strlst = avahi_string_list_new_from_array ((const char **) elements, count); ++ ++cleanup: ++ while (--i >= 0) ++ free (elements[i]); ++ ++ free (elements); ++ return (strlst); ++} ++ ++ ++/* ++ * 'avahi_entry_group_cb()' - Avahi entry group callback function. ++ */ ++static void ++avahi_entry_group_cb (AvahiEntryGroup *group, ++ AvahiEntryGroupState state, ++ void *userdata) ++{ ++ char *name; ++ ++ if (userdata) ++ name = ((cupsd_printer_t *) userdata)->reg_name; ++ else ++ name = "CUPS web interface"; ++ ++ switch (state) ++ { ++ case AVAHI_ENTRY_GROUP_UNCOMMITED: ++ case AVAHI_ENTRY_GROUP_REGISTERING: ++ break; ++ ++ case AVAHI_ENTRY_GROUP_ESTABLISHED: ++ cupsdLogMessage (CUPSD_LOG_DEBUG, ++ "Avahi entry group established for %s", name); ++ break; ++ ++ default: ++ cupsdLogMessage (CUPSD_LOG_DEBUG, ++ "Avahi entry group %s has state %d", ++ name, state); ++ break; ++ } ++} ++ ++/* ++ * 'avahi_client_cb()' - Avahi client callback function. ++ */ ++static void ++avahi_client_cb (AvahiClient *client, ++ AvahiClientState state, ++ void *userdata) ++{ ++ cupsd_printer_t *printer; ++ switch (state) ++ { ++ case AVAHI_CLIENT_S_RUNNING: ++ /* ++ * Avahi client started successfully. ++ */ ++ AvahiCupsClient = client; ++ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client started"); ++ ++ cupsdUpdateDNSSDName (); ++ ++ for (printer = (cupsd_printer_t *)cupsArrayFirst(DNSSDPrinters); ++ printer; ++ printer = (cupsd_printer_t *)cupsArrayNext(DNSSDPrinters)) ++ { ++ if (!printer->avahi_group) ++ dnssdRegisterPrinter (printer); ++ } ++ ++ break; ++ ++ case AVAHI_CLIENT_CONNECTING: ++ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client connecting"); ++ break; ++ ++ case AVAHI_CLIENT_FAILURE: ++ cupsdLogMessage (CUPSD_LOG_ERROR, "Avahi client failed"); ++ break; ++ ++ default: ++ cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client state: %d", state); ++ } ++} ++#endif /* HAVE_AVAHI */ ++ ++ + /* + * 'get_auth_info_required()' - Get the auth-info-required value to advertise. + */ +diff -up cups-1.4.5/scheduler/dirsvc.h.avahi cups-1.4.5/scheduler/dirsvc.h +--- cups-1.4.5/scheduler/dirsvc.h.avahi 2009-05-14 18:54:37.000000000 +0100 ++++ cups-1.4.5/scheduler/dirsvc.h 2010-12-24 13:11:38.344340724 +0000 +@@ -32,6 +32,10 @@ + # endif /* HAVE_LDAP_SSL_H */ + #endif /* HAVE_LDAP */ + ++#ifdef HAVE_AVAHI ++# include <avahi-client/publish.h> ++#endif /* HAVE_AVAHI */ ++ + /* + * Browse protocols... + */ +@@ -132,17 +136,20 @@ VAR int PollPipe VALUE(0); + VAR cupsd_statbuf_t *PollStatusBuffer VALUE(NULL); + /* Status buffer for pollers */ + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++VAR int DNSSDPort VALUE(0); ++ /* Port number to register */ + VAR char *DNSSDComputerName VALUE(NULL), + /* Computer/server name */ + *DNSSDHostName VALUE(NULL); + /* Hostname */ +-VAR cups_array_t *DNSSDAlias VALUE(NULL); +- /* List of dynamic ServerAlias's */ +-VAR int DNSSDPort VALUE(0); +- /* Port number to register */ + VAR cups_array_t *DNSSDPrinters VALUE(NULL); + /* Printers we have registered */ ++#endif /* HAVE_DNSSD || HAVE_AVAHI */ ++ ++#ifdef HAVE_DNSSD ++VAR cups_array_t *DNSSDAlias VALUE(NULL); ++ /* List of dynamic ServerAlias's */ + VAR DNSServiceRef DNSSDRef VALUE(NULL), + /* Master DNS-SD service reference */ + WebIFRef VALUE(NULL), +@@ -151,6 +158,15 @@ VAR DNSServiceRef DNSSDRef VALUE(NULL), + /* Remote printer browse reference */ + #endif /* HAVE_DNSSD */ + ++#ifdef HAVE_AVAHI ++VAR AvahiCupsPoll *AvahiCupsPollHandle VALUE(NULL); ++ /* AvahiCupsPoll object */ ++VAR AvahiClient *AvahiCupsClient VALUE(NULL); ++ /* AvahiClient object */ ++VAR AvahiEntryGroup *AvahiWebIFGroup VALUE(NULL); ++ /* Web interface entry group */ ++#endif /* HAVE_AVAHI */ ++ + #ifdef HAVE_LIBSLP + VAR SLPHandle BrowseSLPHandle VALUE(NULL); + /* SLP API handle */ +@@ -198,9 +214,9 @@ extern void cupsdStartBrowsing(void); + extern void cupsdStartPolling(void); + extern void cupsdStopBrowsing(void); + extern void cupsdStopPolling(void); +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + extern void cupsdUpdateDNSSDName(void); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + #ifdef HAVE_LDAP + extern void cupsdUpdateLDAPBrowse(void); + #endif /* HAVE_LDAP */ +diff -up cups-1.4.5/scheduler/main.c.avahi cups-1.4.5/scheduler/main.c +--- cups-1.4.5/scheduler/main.c.avahi 2010-12-24 13:11:33.633464718 +0000 ++++ cups-1.4.5/scheduler/main.c 2010-12-24 13:11:38.348340619 +0000 +@@ -161,6 +161,10 @@ main(int argc, /* I - Number of comm + int launchd_idle_exit; + /* Idle exit on select timeout? */ + #endif /* HAVE_LAUNCHD */ ++#ifdef HAVE_AVAHI ++ cupsd_timeout_t *tmo; /* Next scheduled timed callback */ ++ long tmo_delay; /* Time before it must be called */ ++#endif /* HAVE_AVAHI */ + + + #ifdef HAVE_GETEUID +@@ -561,6 +565,14 @@ main(int argc, /* I - Number of comm + + httpInitialize(); + ++#ifdef HAVE_AVAHI ++ /* ++ * Initialize timed callback structures. ++ */ ++ ++ cupsdInitTimeouts(); ++#endif /* HAVE_AVAHI */ ++ + cupsdStartServer(); + + /* +@@ -900,6 +912,16 @@ main(int argc, /* I - Number of comm + } + #endif /* __APPLE__ */ + ++#ifdef HAVE_AVAHI ++ /* ++ * If a timed callback is due, run it. ++ */ ++ ++ tmo = cupsdNextTimeout (&tmo_delay); ++ if (tmo && tmo_delay == 0) ++ cupsdRunTimeout (tmo); ++#endif /* HAVE_AVAHI */ ++ + #ifndef __APPLE__ + /* + * Update the network interfaces once a minute... +@@ -1925,6 +1947,10 @@ select_timeout(int fds) /* I - Number + cupsd_job_t *job; /* Job information */ + cupsd_subscription_t *sub; /* Subscription information */ + const char *why; /* Debugging aid */ ++#ifdef HAVE_AVAHI ++ cupsd_timeout_t *tmo; /* Timed callback */ ++ long tmo_delay; /* Seconds before calling it */ ++#endif /* HAVE_AVAHI */ + + + /* +@@ -1967,6 +1993,19 @@ select_timeout(int fds) /* I - Number + } + #endif /* __APPLE__ */ + ++#ifdef HAVE_AVAHI ++ /* ++ * See if there are any scheduled timed callbacks to run. ++ */ ++ ++ tmo = cupsdNextTimeout (&tmo_delay); ++ if (tmo) ++ { ++ timeout = tmo_delay; ++ why = "run a timed callback"; ++ } ++#endif /* HAVE_AVAHI */ ++ + /* + * Check whether we are accepting new connections... + */ +diff -up cups-1.4.5/scheduler/Makefile.avahi cups-1.4.5/scheduler/Makefile +--- cups-1.4.5/scheduler/Makefile.avahi 2010-12-24 13:11:33.739461928 +0000 ++++ cups-1.4.5/scheduler/Makefile 2010-12-24 13:11:38.332341040 +0000 +@@ -17,6 +17,7 @@ include ../Makedefs + + CUPSDOBJS = \ + auth.o \ ++ avahi.o \ + banners.o \ + cert.o \ + classes.o \ +@@ -39,7 +40,8 @@ CUPSDOBJS = \ + server.o \ + statbuf.o \ + subscriptions.o \ +- sysman.o ++ sysman.o \ ++ timeout.o + LIBOBJS = \ + filter.o \ + mime.o \ +diff -up cups-1.4.5/scheduler/printers.c.avahi cups-1.4.5/scheduler/printers.c +--- cups-1.4.5/scheduler/printers.c.avahi 2010-12-24 13:11:33.784460744 +0000 ++++ cups-1.4.5/scheduler/printers.c 2010-12-24 13:11:38.356340409 +0000 +@@ -929,10 +929,10 @@ cupsdDeletePrinter( + cupsdClearString(&p->alert); + cupsdClearString(&p->alert_description); + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + cupsdClearString(&p->product); + cupsdClearString(&p->pdl); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + + cupsArrayDelete(p->filetypes); + +@@ -1301,9 +1301,9 @@ cupsdLoadAllPrinters(void) + { + if (value) + { +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + p->product = _cupsStrAlloc(value); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, +@@ -1717,10 +1717,10 @@ cupsdSaveAllPrinters(void) + + cupsFilePrintf(fp, "Type %d\n", printer->type); + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + if (printer->product) + cupsFilePutConf(fp, "Product", printer->product); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + + for (ptr = (char *)cupsArrayFirst(printer->filters); + ptr; +@@ -3860,7 +3860,7 @@ add_printer_formats(cupsd_printer_t *p) + attr->values[i].string.text = _cupsStrAlloc(mimetype); + } + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + { + char pdl[1024]; /* Buffer to build pdl list */ + mime_filter_t *filter; /* MIME filter looping var */ +@@ -3914,7 +3914,7 @@ add_printer_formats(cupsd_printer_t *p) + + cupsdSetString(&p->pdl, pdl); + } +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + } + + +@@ -4951,9 +4951,9 @@ load_ppd(cupsd_printer_t *p) /* I - Pri + attr->values[i].string.text = _cupsStrAlloc("bcp"); + } + +-#ifdef HAVE_DNSSD ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + cupsdSetString(&p->product, ppd->product); +-#endif /* HAVE_DNSSD */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + + if (ppdFindAttr(ppd, "APRemoteQueueID", NULL)) + p->type |= CUPS_PRINTER_REMOTE; +diff -up cups-1.4.5/scheduler/printers.h.avahi cups-1.4.5/scheduler/printers.h +--- cups-1.4.5/scheduler/printers.h.avahi 2010-03-30 23:07:33.000000000 +0100 ++++ cups-1.4.5/scheduler/printers.h 2010-12-24 13:11:38.357340382 +0000 +@@ -16,6 +16,9 @@ + #ifdef HAVE_DNSSD + # include <dns_sd.h> + #endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++# include "avahi.h" ++#endif /* HAVE_AVAHI */ + #include <cups/pwg-private.h> + + +@@ -99,17 +102,24 @@ typedef struct cupsd_printer_s + char *recoverable; /* com.apple.print.recoverable-message */ + _pwg_t *pwg; /* PWG<->PPD mapping data */ + ++#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) ++ char *reg_name; /* Name used for service registration */ ++ char *product, /* PPD Product string */ ++ *pdl; /* pdl value for TXT record */ ++#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */ + #ifdef HAVE_DNSSD +- char *reg_name, /* Name used for service registration */ +- *product, /* PPD Product string */ +- *pdl, /* pdl value for TXT record */ +- *ipp_txt, /* IPP TXT record contents */ ++ char *ipp_txt, /* IPP TXT record contents */ + *printer_txt; /* LPD TXT record contents */ + int ipp_len, /* IPP TXT record length */ + printer_len; /* LPD TXT record length */ + DNSServiceRef ipp_ref, /* Reference for _ipp._tcp,_cups */ + printer_ref; /* Reference for _printer._tcp */ + #endif /* HAVE_DNSSD */ ++#ifdef HAVE_AVAHI ++ AvahiStringList *ipp_txt, /* IPP TXT record */ ++ *printer_txt; /* LPD TXT record */ ++ AvahiEntryGroup *avahi_group; /* Avahi entry group */ ++#endif /* HAVE_AVAHI */ + } cupsd_printer_t; + + +diff -up cups-1.4.5/scheduler/timeout.c.avahi cups-1.4.5/scheduler/timeout.c +--- cups-1.4.5/scheduler/timeout.c.avahi 2010-12-24 13:11:38.358340356 +0000 ++++ cups-1.4.5/scheduler/timeout.c 2010-12-24 13:11:38.358340356 +0000 +@@ -0,0 +1,191 @@ ++/* ++ * "$Id$" ++ * ++ * Timeout functions for the Common UNIX Printing System (CUPS). ++ * ++ * Copyright (C) 2010 Red Hat, Inc. ++ * Authors: ++ * Tim Waugh twaugh@redhat.com ++ * ++ * Distribution and use rights are outlined in the file "LICENSE.txt" ++ * which should have been included with this file. If this file is ++ * file is missing or damaged, see the license at "http://www.cups.org/". ++ * ++ * Contents: ++ * ++ * cupsdInitTimeouts() - Initialise timeout structure. ++ * cupsdAddTimeout() - Add a timed callback. ++ * cupsdNextTimeout() - Find the next enabled timed callback. ++ * cupsdUpdateTimeout() - Adjust the time of a timed callback or disable it. ++ * cupsdRemoveTimeout() - Discard a timed callback. ++ * compare_timeouts() - Compare timed callbacks for array sorting. ++ */ ++ ++#include <config.h> ++ ++#ifdef HAVE_AVAHI /* Applies to entire file... */ ++ ++/* ++ * Include necessary headers... ++ */ ++ ++#include "cupsd.h" ++ ++#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) ++# include <malloc.h> ++#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ ++ ++#ifdef HAVE_AVAHI ++# include <avahi-common/timeval.h> ++#endif /* HAVE_AVAHI */ ++ ++ ++struct _cupsd_timeout_s ++{ ++ struct timeval when; ++ int enabled; ++ cupsd_timeoutfunc_t callback; ++ void *data; ++}; ++ ++/* ++ * Local functions... ++ */ ++ ++/* ++ * 'compare_timeouts()' - Compare timed callbacks for array sorting. ++ */ ++ ++static int ++compare_timeouts (cupsd_timeout_t *p0, cupsd_timeout_t *p1) ++{ ++ if (!p0->enabled || !p1->enabled) ++ { ++ if (!p0->enabled && !p1->enabled) ++ return (0); ++ ++ return (p0->enabled ? -1 : 1); ++ } ++ ++ return (avahi_timeval_compare (&p0->when, &p1->when)); ++} ++ ++ ++/* ++ * 'cupsdInitTimeouts()' - Initialise timeout structures. ++ */ ++ ++void ++cupsdInitTimeouts(void) ++{ ++ Timeouts = cupsArrayNew ((cups_array_func_t)compare_timeouts, NULL); ++} ++ ++ ++/* ++ * 'cupsdAddTimeout()' - Add a timed callback. ++ */ ++ ++cupsd_timeout_t * /* O - Timeout handle */ ++cupsdAddTimeout(const struct timeval *tv, /* I - Absolute time */ ++ cupsd_timeoutfunc_t cb, /* I - Callback function */ ++ void *data) /* I - User data */ ++{ ++ cupsd_timeout_t *timeout; ++ ++ timeout = malloc (sizeof(cupsd_timeout_t)); ++ if (timeout != NULL) ++ { ++ timeout->enabled = (tv != NULL); ++ if (tv) ++ { ++ timeout->when.tv_sec = tv->tv_sec; ++ timeout->when.tv_usec = tv->tv_usec; ++ } ++ ++ timeout->callback = cb; ++ timeout->data = data; ++ cupsArrayAdd (Timeouts, timeout); ++ } ++ ++ return timeout; ++} ++ ++ ++/* ++ * 'cupsdNextTimeout()' - Find the next enabled timed callback. ++ */ ++ ++cupsd_timeout_t * /* O - Next enabled timeout or NULL */ ++cupsdNextTimeout(long *delay) /* O - Seconds before scheduled */ ++{ ++ cupsd_timeout_t *first = cupsArrayFirst (Timeouts); ++ struct timeval curtime; ++ ++ if (first && !first->enabled) ++ first = NULL; ++ ++ if (first && delay) ++ { ++ gettimeofday (&curtime, NULL); ++ if (avahi_timeval_compare (&curtime, &first->when) > 0) ++ { ++ *delay = 0; ++ } else { ++ *delay = 1 + first->when.tv_sec - curtime.tv_sec; ++ if (first->when.tv_usec < curtime.tv_usec) ++ (*delay)--; ++ } ++ } ++ ++ return (first); ++} ++ ++ ++/* ++ * 'cupsdRunTimeout()' - Run a timed callback. ++ */ ++ ++void ++cupsdRunTimeout(cupsd_timeout_t *timeout) /* I - Timeout */ ++{ ++ timeout->enabled = 0; ++ timeout->callback (timeout, timeout->data); ++} ++ ++/* ++ * 'cupsdUpdateTimeout()' - Adjust the time of a timed callback or disable it. ++ */ ++ ++void ++cupsdUpdateTimeout(cupsd_timeout_t *timeout, /* I - Timeout */ ++ const struct timeval *tv) /* I - Absolute time or NULL */ ++{ ++ cupsArrayRemove (Timeouts, timeout); ++ timeout->enabled = (tv != NULL); ++ if (tv) ++ { ++ timeout->when.tv_sec = tv->tv_sec; ++ timeout->when.tv_usec = tv->tv_usec; ++ } ++ cupsArrayAdd (Timeouts, timeout); ++} ++ ++ ++/* ++ * 'cupsdRemoveTimeout()' - Discard a timed callback. ++ */ ++ ++void ++cupsdRemoveTimeout(cupsd_timeout_t *timeout) /* I - Timeout */ ++{ ++ cupsArrayRemove (Timeouts, timeout); ++ free (timeout); ++} ++ ++ ++#endif /* HAVE_AVAHI ... from top of file */ ++ ++/* ++ * End of "$Id$". ++ */ diff --git a/pkgs/core/cups/patches/cups-banners.patch b/pkgs/core/cups/patches/cups-banners.patch new file mode 100644 index 0000000..6907c91 --- /dev/null +++ b/pkgs/core/cups/patches/cups-banners.patch @@ -0,0 +1,11 @@ +--- cups-1.2rc2/scheduler/banners.c.banners 2006-04-19 16:12:07.000000000 +0100 ++++ cups-1.2rc2/scheduler/banners.c 2006-04-19 16:12:42.000000000 +0100 +@@ -119,6 +119,8 @@ + if ((ext = strrchr(dent->filename, '.')) != NULL) + if (!strcmp(ext, ".bck") || + !strcmp(ext, ".bak") || ++ !strcmp(ext, ".rpmnew") || ++ !strcmp(ext, ".rpmsave") || + !strcmp(ext, ".sav")) + continue; + diff --git a/pkgs/core/cups/patches/cups-build.patch b/pkgs/core/cups/patches/cups-build.patch new file mode 100644 index 0000000..727deb2 --- /dev/null +++ b/pkgs/core/cups/patches/cups-build.patch @@ -0,0 +1,42 @@ +diff -up cups-1.4rc1/Makedefs.in.build cups-1.4rc1/Makedefs.in +--- cups-1.4rc1/Makedefs.in.build 2009-05-27 00:27:06.000000000 +0100 ++++ cups-1.4rc1/Makedefs.in 2009-06-17 11:18:27.185443255 +0100 +@@ -124,7 +124,7 @@ ARFLAGS = @ARFLAGS@ + BACKLIBS = @BACKLIBS@ + BANNERTOPS = @BANNERTOPS@ + CFLAGS = @CPPFLAGS@ @CFLAGS@ +-COMMONLIBS = @LIBS@ ++COMMONLIBS = @LIBS@ $(DNSSDLIBS) + CUPSDLIBS = @CUPSDLIBS@ + CXXFLAGS = @CPPFLAGS@ @CXXFLAGS@ + CXXLIBS = @CXXLIBS@ +diff -up cups-1.4rc1/scheduler/dirsvc.c.build cups-1.4rc1/scheduler/dirsvc.c +--- cups-1.4rc1/scheduler/dirsvc.c.build 2009-05-14 18:54:37.000000000 +0100 ++++ cups-1.4rc1/scheduler/dirsvc.c 2009-06-17 11:23:23.366318546 +0100 +@@ -2042,7 +2042,7 @@ cupsdUpdateDNSSDName(void) + + WebIFRef = DNSSDRef; + if ((error = DNSServiceRegister(&WebIFRef, +- kDNSServiceFlagsShareConnection, ++ 0, + 0, webif, "_http._tcp", NULL, + NULL, htons(DNSSDPort), 7, + "\006path=/", dnssdRegisterCallback, +@@ -2765,7 +2765,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p) + do + { + p->ipp_ref = DNSSDRef; +- if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection, ++ if ((se = DNSServiceRegister(&p->ipp_ref, 0, + 0, name, regtype, NULL, NULL, + htons(DNSSDPort), ipp_len, ipp_txt, + dnssdRegisterCallback, +@@ -2854,7 +2854,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p) + + p->printer_ref = DNSSDRef; + if ((se = DNSServiceRegister(&p->printer_ref, +- kDNSServiceFlagsShareConnection, ++ 0, + 0, name, "_printer._tcp", NULL, NULL, + htons(515), printer_len, printer_txt, + dnssdRegisterCallback, diff --git a/pkgs/core/cups/patches/cups-cups-get-classes.patch b/pkgs/core/cups/patches/cups-cups-get-classes.patch new file mode 100644 index 0000000..196f5f1 --- /dev/null +++ b/pkgs/core/cups/patches/cups-cups-get-classes.patch @@ -0,0 +1,90 @@ +diff -up cups-1.4rc1/cups/dest.c.cups-get-classes cups-1.4rc1/cups/dest.c +--- cups-1.4rc1/cups/dest.c.cups-get-classes 2009-05-13 22:39:17.000000000 +0100 ++++ cups-1.4rc1/cups/dest.c 2009-07-28 22:17:40.285709944 +0100 +@@ -1735,6 +1735,7 @@ cups_get_sdests(http_t *http, /* I + char uri[1024]; /* printer-uri value */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ ++ int get_classes; /* Whether we need to fetch class */ + #ifdef __APPLE__ + char media_default[41]; /* Default paper size */ + #endif /* __APPLE__ */ +@@ -1791,6 +1792,8 @@ cups_get_sdests(http_t *http, /* I + * printer-uri [for IPP_GET_PRINTER_ATTRIBUTES] + */ + ++ get_classes = (op == CUPS_GET_PRINTERS); ++ + request = ippNewRequest(op); + + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, +@@ -1848,6 +1851,23 @@ cups_get_sdests(http_t *http, /* I + attr->value_tag != IPP_TAG_URI) + continue; + ++ if (get_classes && ++ ++ /* Is this a class? */ ++ ((attr->value_tag == IPP_TAG_ENUM && ++ !strcmp(attr->name, "printer-type") && ++ (attr->values[0].integer & CUPS_PRINTER_CLASS)) || ++ ++ /* Or, is this an attribute from CUPS 1.2 or later? */ ++ !strcmp(attr->name, "auth-info-required") || ++ !strncmp(attr->name, "marker-", 7) || ++ !strcmp(attr->name, "printer-commands") || ++ !strcmp(attr->name, "printer-is-shared"))) ++ /* We are talking to a recent enough CUPS server that ++ * CUPS_GET_PRINTERS returns classes as well. ++ */ ++ get_classes = 0; ++ + if (!strcmp(attr->name, "auth-info-required") || + !strcmp(attr->name, "device-uri") || + !strcmp(attr->name, "marker-change-time") || +@@ -1939,6 +1959,28 @@ cups_get_sdests(http_t *http, /* I + continue; + } + ++ /* ++ * If we sent a CUPS_GET_CLASSES request, check whether ++ * CUPS_GET_PRINTERS already gave us this destination and exit ++ * early if so. ++ */ ++ ++ if (op == CUPS_GET_CLASSES) ++ { ++ int diff; ++ cups_find_dest (printer_name, NULL, num_dests, *dests, 0, &diff); ++ if (diff == 0) ++ { ++ /* ++ * Found it. The CUPS server already gave us the classes in ++ * its CUPS_GET_PRINTERS response. ++ */ ++ ++ cupsFreeOptions(num_options, options); ++ break; ++ } ++ } ++ + if ((dest = cups_add_dest(printer_name, NULL, &num_dests, dests)) != NULL) + { + dest->num_options = num_options; +@@ -1955,6 +1997,16 @@ cups_get_sdests(http_t *http, /* I + } + + /* ++ * If this is a CUPS_GET_PRINTERS request but we didn't see any ++ * classes we might be talking to an older CUPS server that requires ++ * CUPS_GET_CLASSES as well. ++ */ ++ ++ if (get_classes) ++ num_dests = cups_get_sdests (http, CUPS_GET_CLASSES, name, ++ num_dests, dests); ++ ++ /* + * Return the count... + */ + diff --git a/pkgs/core/cups/patches/cups-direct-usb.patch b/pkgs/core/cups/patches/cups-direct-usb.patch new file mode 100644 index 0000000..2724fad --- /dev/null +++ b/pkgs/core/cups/patches/cups-direct-usb.patch @@ -0,0 +1,27 @@ +diff -up cups-1.3.7/backend/usb-unix.c.direct-usb cups-1.3.7/backend/usb-unix.c +--- cups-1.3.7/backend/usb-unix.c.direct-usb 2008-03-26 16:02:45.000000000 +0000 ++++ cups-1.3.7/backend/usb-unix.c 2008-07-15 13:25:56.000000000 +0100 +@@ -94,6 +94,9 @@ print_device(const char *uri, /* I - De + strncasecmp(hostname, "Minolta", 7); + #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */ + ++ if (use_bc && !strncmp(uri, "usb:/dev/", 9)) ++ use_bc = 0; ++ + if ((device_fd = open_device(uri, &use_bc)) == -1) + { + if (getenv("CLASS") != NULL) +@@ -320,12 +323,7 @@ open_device(const char *uri, /* I - Dev + if (!strncmp(uri, "usb:/dev/", 9)) + #ifdef __linux + { +- /* +- * Do not allow direct devices anymore... +- */ +- +- errno = ENODEV; +- return (-1); ++ return (open(uri + 4, O_RDWR | O_EXCL)); + } + else if (!strncmp(uri, "usb://", 6)) + { diff --git a/pkgs/core/cups/patches/cups-dnssd-deviceid.patch b/pkgs/core/cups/patches/cups-dnssd-deviceid.patch new file mode 100644 index 0000000..abb8366 --- /dev/null +++ b/pkgs/core/cups/patches/cups-dnssd-deviceid.patch @@ -0,0 +1,38 @@ +diff -up cups-1.4.3/backend/dnssd.c.dnssd-deviceid.patch cups-1.4.3/backend/dnssd.c +--- cups-1.4.3/backend/dnssd.c.dnssd-deviceid.patch 2010-04-16 19:36:12.226148774 +0100 ++++ cups-1.4.3/backend/dnssd.c 2010-04-16 19:39:53.314148240 +0100 +@@ -1192,15 +1192,22 @@ find_device (cups_array_t *devices, + if (device->device_id) + free(device->device_id); + ++ if (device_id[0]) ++ { ++ /* Mark this as the real device ID. */ ++ ptr = device_id + strlen(device_id); ++ snprintf(ptr, sizeof(device_id) - (ptr - device_id), "FZY:0;"); ++ } ++ + if (!device_id[0] && strcmp(model, "Unknown")) + { + if (make_and_model[0]) +- snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", ++ snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;FZY:1;", + make_and_model, model); + else if (!strncasecmp(model, "designjet ", 10)) +- snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s", model + 10); ++ snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;FZY:1;", model + 10); + else if (!strncasecmp(model, "stylus ", 7)) +- snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s", model + 7); ++ snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;FZY:1;", model + 7); + else if ((ptr = strchr(model, ' ')) != NULL) + { + /* +@@ -1210,7 +1217,7 @@ find_device (cups_array_t *devices, + memcpy(make_and_model, model, ptr - model); + make_and_model[ptr - model] = '\0'; + +- snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s", ++ snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;FZY:1;", + make_and_model, ptr + 1); + } + } diff --git a/pkgs/core/cups/patches/cups-driverd-timeout.patch b/pkgs/core/cups/patches/cups-driverd-timeout.patch new file mode 100644 index 0000000..222fb09 --- /dev/null +++ b/pkgs/core/cups/patches/cups-driverd-timeout.patch @@ -0,0 +1,21 @@ +diff -up cups-1.3.7/scheduler/ipp.c.driverd-timeout cups-1.3.7/scheduler/ipp.c +--- cups-1.3.7/scheduler/ipp.c.driverd-timeout 2008-07-15 13:40:51.000000000 +0100 ++++ cups-1.3.7/scheduler/ipp.c 2008-07-15 13:40:51.000000000 +0100 +@@ -4293,7 +4293,7 @@ copy_model(cupsd_client_t *con, /* I - + close(temppipe[1]); + + /* +- * Wait up to 30 seconds for the PPD file to be copied... ++ * Wait up to 70 seconds for the PPD file to be copied... + */ + + total = 0; +@@ -4315,7 +4315,7 @@ copy_model(cupsd_client_t *con, /* I - + FD_SET(temppipe[0], &input); + FD_SET(CGIPipes[0], &input); + +- timeout.tv_sec = 30; ++ timeout.tv_sec = 70; + timeout.tv_usec = 0; + + if ((i = select(maxfd, &input, NULL, NULL, &timeout)) < 0) diff --git a/pkgs/core/cups/patches/cups-eggcups.patch b/pkgs/core/cups/patches/cups-eggcups.patch new file mode 100644 index 0000000..fde1e07 --- /dev/null +++ b/pkgs/core/cups/patches/cups-eggcups.patch @@ -0,0 +1,130 @@ +diff -up cups-1.4b1/backend/ipp.c.eggcups cups-1.4b1/backend/ipp.c +--- cups-1.4b1/backend/ipp.c.eggcups 2008-10-15 19:27:45.000000000 +0100 ++++ cups-1.4b1/backend/ipp.c 2008-11-11 15:43:30.000000000 +0000 +@@ -51,6 +51,70 @@ static char pstmpname[1024] = ""; /* Tem + static char tmpfilename[1024] = ""; /* Temporary spool file name */ + static int job_cancelled = 0; /* Job cancelled? */ + ++#if HAVE_DBUS ++#include <dbus/dbus.h> ++ ++static DBusConnection *dbus_connection = NULL; ++ ++static int ++init_dbus (void) ++{ ++ DBusConnection *connection; ++ DBusError error; ++ ++ if (dbus_connection && ++ !dbus_connection_get_is_connected (dbus_connection)) { ++ dbus_connection_unref (dbus_connection); ++ dbus_connection = NULL; ++ } ++ ++ dbus_error_init (&error); ++ connection = dbus_bus_get (getuid () ? DBUS_BUS_SESSION : DBUS_BUS_SYSTEM, &error); ++ if (connection == NULL) { ++ dbus_error_free (&error); ++ return -1; ++ } ++ ++ dbus_connection = connection; ++ return 0; ++} ++ ++int ++dbus_broadcast_queued_remote (const char *printer_uri, ++ ipp_status_t status, ++ unsigned int local_job_id, ++ unsigned int remote_job_id, ++ const char *username, ++ const char *printer_name) ++{ ++ DBusMessage *message; ++ DBusMessageIter iter; ++ const char *errstr; ++ ++ if (!dbus_connection || !dbus_connection_get_is_connected (dbus_connection)) { ++ if (init_dbus () || !dbus_connection) ++ return -1; ++ } ++ ++ errstr = ippErrorString (status); ++ message = dbus_message_new_signal ("/com/redhat/PrinterSpooler", ++ "com.redhat.PrinterSpooler", ++ "JobQueuedRemote"); ++ dbus_message_iter_init_append (message, &iter); ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &printer_uri); ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &errstr); ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &local_job_id); ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &remote_job_id); ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &username); ++ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &printer_name); ++ ++ dbus_connection_send (dbus_connection, message, NULL); ++ dbus_connection_flush (dbus_connection); ++ dbus_message_unref (message); ++ ++ return 0; ++} ++#endif /* HAVE_DBUS */ + + /* + * Local functions... +@@ -1058,6 +1122,15 @@ main(int argc, /* I - Number of comm + job_id); + } + ++#if HAVE_DBUS ++ dbus_broadcast_queued_remote (argv[0], ++ ipp_status, ++ atoi (argv[1]), ++ job_id, ++ argv[2], ++ getenv ("PRINTER")); ++#endif /* HAVE_DBUS */ ++ + ippDelete(response); + + if (job_cancelled) +diff -up cups-1.4b1/backend/Makefile.eggcups cups-1.4b1/backend/Makefile +--- cups-1.4b1/backend/Makefile.eggcups 2008-10-06 22:08:27.000000000 +0100 ++++ cups-1.4b1/backend/Makefile 2008-11-11 15:45:31.000000000 +0000 +@@ -188,7 +188,7 @@ dnssd: dnssd.o ../cups/$(LIBCUPS) libbac + + ipp: ipp.o ../cups/$(LIBCUPS) libbackend.a + echo Linking $@... +- $(CC) $(LDFLAGS) -o ipp ipp.o libbackend.a $(LIBS) ++ $(CC) $(LDFLAGS) -o ipp ipp.o libbackend.a $(LIBS) $(CUPSDLIBS) + $(RM) http + $(LN) ipp http + +diff -up cups-1.4b1/scheduler/subscriptions.c.eggcups cups-1.4b1/scheduler/subscriptions.c +--- cups-1.4b1/scheduler/subscriptions.c.eggcups 2008-08-01 22:11:55.000000000 +0100 ++++ cups-1.4b1/scheduler/subscriptions.c 2008-11-11 15:43:30.000000000 +0000 +@@ -1302,13 +1302,13 @@ cupsd_send_dbus(cupsd_eventmask_t event, + what = "PrinterAdded"; + else if (event & CUPSD_EVENT_PRINTER_DELETED) + what = "PrinterRemoved"; +- else if (event & CUPSD_EVENT_PRINTER_CHANGED) +- what = "QueueChanged"; + else if (event & CUPSD_EVENT_JOB_CREATED) + what = "JobQueuedLocal"; + else if ((event & CUPSD_EVENT_JOB_STATE) && job && + job->state_value == IPP_JOB_PROCESSING) + what = "JobStartedLocal"; ++ else if (event & (CUPSD_EVENT_PRINTER_CHANGED|CUPSD_EVENT_JOB_STATE_CHANGED|CUPSD_EVENT_PRINTER_STATE_CHANGED)) ++ what = "QueueChanged"; + else + return; + +@@ -1344,7 +1344,7 @@ cupsd_send_dbus(cupsd_eventmask_t event, + dbus_message_append_iter_init(message, &iter); + if (dest) + dbus_message_iter_append_string(&iter, dest->name); +- if (job) ++ if (job && strcmp (what, "QueueChanged") != 0) + { + dbus_message_iter_append_uint32(&iter, job->id); + dbus_message_iter_append_string(&iter, job->username); diff --git a/pkgs/core/cups/patches/cups-filter-debug.patch b/pkgs/core/cups/patches/cups-filter-debug.patch new file mode 100644 index 0000000..38053e6 --- /dev/null +++ b/pkgs/core/cups/patches/cups-filter-debug.patch @@ -0,0 +1,32 @@ +diff -up cups-1.4rc1/scheduler/job.c.filter-debug cups-1.4rc1/scheduler/job.c +--- cups-1.4rc1/scheduler/job.c.filter-debug 2009-06-23 18:10:57.125572911 +0100 ++++ cups-1.4rc1/scheduler/job.c 2009-06-23 18:11:31.495572481 +0100 +@@ -544,10 +544,28 @@ cupsdContinueJob(cupsd_job_t *job) /* I + + if (!filters) + { ++ mime_filter_t *current; ++ + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Unable to convert file %d to printable format!", + job->current_file); + ++ cupsdLogJob(job, CUPSD_LOG_ERROR, ++ "Required: %s/%s -> %s/%s", ++ job->filetypes[job->current_file]->super, ++ job->filetypes[job->current_file]->type, ++ job->printer->filetype->super, ++ job->printer->filetype->type); ++ ++ for (current = (mime_filter_t *)cupsArrayFirst(MimeDatabase->srcs); ++ current; ++ current = (mime_filter_t *)cupsArrayNext(MimeDatabase->srcs)) ++ cupsdLogJob(job, CUPSD_LOG_ERROR, ++ "Available: %s/%s -> %s/%s (%s)", ++ current->src->super, current->src->type, ++ current->dst->super, current->dst->type, ++ current->filter); ++ + abort_message = "Aborting job because it cannot be printed."; + abort_state = IPP_JOB_ABORTED; + diff --git a/pkgs/core/cups/patches/cups-force-gnutls.patch b/pkgs/core/cups/patches/cups-force-gnutls.patch new file mode 100644 index 0000000..85adaa8 --- /dev/null +++ b/pkgs/core/cups/patches/cups-force-gnutls.patch @@ -0,0 +1,89 @@ +diff -up cups-1.4.4/config-scripts/cups-ssl.m4.force-gnutls cups-1.4.4/config-scripts/cups-ssl.m4 +--- cups-1.4.4/config-scripts/cups-ssl.m4.force-gnutls 2010-09-15 16:49:22.343502552 +0100 ++++ cups-1.4.4/config-scripts/cups-ssl.m4 2010-09-15 16:49:42.347502595 +0100 +@@ -65,23 +65,21 @@ if test x$enable_ssl != xno; then + if $PKGCONFIG --exists gnutls; then + if test "x$have_pthread" = xyes; then + AC_MSG_WARN([The current version of GNU TLS cannot be made thread-safe.]) +- else +- have_ssl=1 +- SSLLIBS=`$PKGCONFIG --libs gnutls` +- SSLFLAGS=`$PKGCONFIG --cflags gnutls` +- AC_DEFINE(HAVE_SSL) +- AC_DEFINE(HAVE_GNUTLS) + fi ++ have_ssl=1 ++ SSLLIBS=`$PKGCONFIG --libs gnutls` ++ SSLFLAGS=`$PKGCONFIG --cflags gnutls` ++ AC_DEFINE(HAVE_SSL) ++ AC_DEFINE(HAVE_GNUTLS) + elif test "x$LIBGNUTLSCONFIG" != x; then + if test "x$have_pthread" = xyes; then + AC_MSG_WARN([The current version of GNU TLS cannot be made thread-safe.]) +- else +- have_ssl=1 +- SSLLIBS=`$LIBGNUTLSCONFIG --libs` +- SSLFLAGS=`$LIBGNUTLSCONFIG --cflags` +- AC_DEFINE(HAVE_SSL) +- AC_DEFINE(HAVE_GNUTLS) + fi ++ have_ssl=1 ++ SSLLIBS=`$LIBGNUTLSCONFIG --libs` ++ SSLFLAGS=`$LIBGNUTLSCONFIG --cflags` ++ AC_DEFINE(HAVE_SSL) ++ AC_DEFINE(HAVE_GNUTLS) + fi + + if test $have_ssl = 1; then +diff -up cups-1.4.4/configure.force-gnutls cups-1.4.4/configure +--- cups-1.4.4/configure.force-gnutls 2010-06-17 19:25:47.000000000 +0100 ++++ cups-1.4.4/configure 2010-09-15 16:50:01.689503165 +0100 +@@ -17542,36 +17542,34 @@ fi + if test "x$have_pthread" = xyes; then + { echo "$as_me:$LINENO: WARNING: The current version of GNU TLS cannot be made thread-safe." >&5 + echo "$as_me: WARNING: The current version of GNU TLS cannot be made thread-safe." >&2;} +- else +- have_ssl=1 +- SSLLIBS=`$PKGCONFIG --libs gnutls` +- SSLFLAGS=`$PKGCONFIG --cflags gnutls` +- cat >>confdefs.h <<_ACEOF ++ fi ++ have_ssl=1 ++ SSLLIBS=`$PKGCONFIG --libs gnutls` ++ SSLFLAGS=`$PKGCONFIG --cflags gnutls` ++ cat >>confdefs.h <<_ACEOF + #define HAVE_SSL 1 + _ACEOF + +- cat >>confdefs.h <<_ACEOF ++ cat >>confdefs.h <<_ACEOF + #define HAVE_GNUTLS 1 + _ACEOF + +- fi + elif test "x$LIBGNUTLSCONFIG" != x; then + if test "x$have_pthread" = xyes; then + { echo "$as_me:$LINENO: WARNING: The current version of GNU TLS cannot be made thread-safe." >&5 + echo "$as_me: WARNING: The current version of GNU TLS cannot be made thread-safe." >&2;} +- else +- have_ssl=1 +- SSLLIBS=`$LIBGNUTLSCONFIG --libs` +- SSLFLAGS=`$LIBGNUTLSCONFIG --cflags` +- cat >>confdefs.h <<_ACEOF ++ fi ++ have_ssl=1 ++ SSLLIBS=`$LIBGNUTLSCONFIG --libs` ++ SSLFLAGS=`$LIBGNUTLSCONFIG --cflags` ++ cat >>confdefs.h <<_ACEOF + #define HAVE_SSL 1 + _ACEOF + +- cat >>confdefs.h <<_ACEOF ++ cat >>confdefs.h <<_ACEOF + #define HAVE_GNUTLS 1 + _ACEOF + +- fi + fi + + if test $have_ssl = 1; then diff --git a/pkgs/core/cups/patches/cups-getpass.patch b/pkgs/core/cups/patches/cups-getpass.patch new file mode 100644 index 0000000..1c1da96 --- /dev/null +++ b/pkgs/core/cups/patches/cups-getpass.patch @@ -0,0 +1,43 @@ +diff -up cups-1.4.4/cups/usersys.c.getpass cups-1.4.4/cups/usersys.c +--- cups-1.4.4/cups/usersys.c.getpass 2010-03-30 23:07:33.000000000 +0100 ++++ cups-1.4.4/cups/usersys.c 2010-06-18 09:38:08.368096897 +0100 +@@ -41,6 +41,8 @@ + #include "globals.h" + #include <stdlib.h> + #include <sys/stat.h> ++#include <termios.h> ++#include <signal.h> + #ifdef WIN32 + # include <windows.h> + #else +@@ -406,7 +408,29 @@ _cupsGetPassword(const char *prompt) /* + * Use the standard getpass function to get a password from the console. + */ + +- return (getpass(prompt)); ++ static char password[100]; ++ struct termios oldtio, newtio; ++ sigset_t oldset, newset; ++ int nread; ++ sigprocmask (SIG_BLOCK, NULL, &newset); ++ sigaddset (&newset, SIGINT); ++ sigaddset (&newset, SIGTSTP); ++ sigprocmask (SIG_BLOCK, &newset, &oldset); ++ tcgetattr (STDIN_FILENO, &oldtio); ++ newtio = oldtio; ++ newtio.c_lflag &= ~ECHO; ++ tcsetattr (STDIN_FILENO, TCSAFLUSH, &newtio); ++ fputs (prompt, stdout); ++ fflush (stdout); ++ nread = read (STDIN_FILENO, password, sizeof (password)); ++ tcsetattr (STDIN_FILENO, TCSAFLUSH, &oldtio); ++ fputc ('\n', stdout); ++ sigprocmask (SIG_SETMASK, &oldset, NULL); ++ if (nread > 0) ++ password[nread - 1] = '\0'; ++ else ++ password[0] ='\0'; ++ return password; + #endif /* WIN32 */ + } + diff --git a/pkgs/core/cups/patches/cups-hostnamelookups.patch b/pkgs/core/cups/patches/cups-hostnamelookups.patch new file mode 100644 index 0000000..75b6abf --- /dev/null +++ b/pkgs/core/cups/patches/cups-hostnamelookups.patch @@ -0,0 +1,24 @@ +diff -up cups-1.4.4/scheduler/network.c.hostnamelookups cups-1.4.4/scheduler/network.c +--- cups-1.4.4/scheduler/network.c.hostnamelookups 2010-04-09 23:42:09.000000000 +0100 ++++ cups-1.4.4/scheduler/network.c 2010-06-18 11:13:02.331979867 +0100 +@@ -154,11 +154,7 @@ cupsdNetIFUpdate(void) + * Try looking up the hostname for the address as needed... + */ + +-#ifdef __APPLE__ + if (HostNameLookups) +-#else +- if (HostNameLookups || RemotePort) +-#endif /* __APPLE__ */ + httpAddrLookup((http_addr_t *)(addr->ifa_addr), hostname, + sizeof(hostname)); + else +@@ -166,7 +162,7 @@ cupsdNetIFUpdate(void) + /* + * Map the default server address and localhost to the server name + * and localhost, respectively; for all other addresses, use the +- * dotted notation... ++ * numeric address... + */ + + if (httpAddrLocalhost((http_addr_t *)(addr->ifa_addr))) diff --git a/pkgs/core/cups/patches/cups-hp-deviceid-oid.patch b/pkgs/core/cups/patches/cups-hp-deviceid-oid.patch new file mode 100644 index 0000000..29f0781 --- /dev/null +++ b/pkgs/core/cups/patches/cups-hp-deviceid-oid.patch @@ -0,0 +1,21 @@ +diff -up cups-1.4.3/backend/snmp.c.hp-deviceid-oid cups-1.4.3/backend/snmp.c +--- cups-1.4.3/backend/snmp.c.hp-deviceid-oid 2009-12-08 02:13:42.000000000 +0000 ++++ cups-1.4.3/backend/snmp.c 2010-04-13 15:00:26.486148914 +0100 +@@ -194,6 +194,7 @@ static const int UriOID[] = { CUPS_OID_p + static const int LexmarkProductOID[] = { 1,3,6,1,4,1,641,2,1,2,1,2,1,-1 }; + static const int LexmarkProductOID2[] = { 1,3,6,1,4,1,674,10898,100,2,1,2,1,2,1,-1 }; + static const int LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 }; ++static const int HPDeviceIdOID[] = { 1,3,6,1,4,1,11,2,3,9,1,1,7,0,-1 }; + static const int XeroxProductOID[] = { 1,3,6,1,4,1,128,2,1,3,1,2,0,-1 }; + static cups_array_t *DeviceURIs = NULL; + static int HostNameLookups = 0; +@@ -1003,6 +1004,9 @@ read_snmp_response(int fd) /* I - SNMP + _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, + packet.community, CUPS_ASN1_GET_REQUEST, + DEVICE_PRODUCT, XeroxProductOID); ++ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, ++ packet.community, CUPS_ASN1_GET_REQUEST, ++ DEVICE_ID, HPDeviceIdOID); + break; + + case DEVICE_DESCRIPTION : diff --git a/pkgs/core/cups/patches/cups-logrotate.patch b/pkgs/core/cups/patches/cups-logrotate.patch new file mode 100644 index 0000000..559cbdc --- /dev/null +++ b/pkgs/core/cups/patches/cups-logrotate.patch @@ -0,0 +1,63 @@ +diff -up cups-1.3.5/scheduler/log.c.logrotate cups-1.3.5/scheduler/log.c +--- cups-1.3.5/scheduler/log.c.logrotate 2008-02-14 12:21:25.000000000 +0000 ++++ cups-1.3.5/scheduler/log.c 2008-02-14 12:24:16.000000000 +0000 +@@ -29,6 +29,9 @@ + #include "cupsd.h" + #include <stdarg.h> + #include <syslog.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <unistd.h> + + + /* +@@ -467,12 +470,10 @@ check_log_file(cups_file_t **lf, /* IO - + return (1); + + /* +- * Format the filename as needed... ++ * Format the filename... + */ + +- if (!*lf || +- (strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize && +- MaxLogSize > 0)) ++ if (strncmp(logname, "/dev/", 5)) + { + /* + * Handle format strings... +@@ -565,6 +566,34 @@ check_log_file(cups_file_t **lf, /* IO - + } + + /* ++ * Has someone else (i.e. logrotate) already rotated the log for us? ++ */ ++ else if (strncmp(filename, "/dev/", 5)) ++ { ++ struct stat st; ++ if (stat(filename, &st) || st.st_size == 0) ++ { ++ /* File is either missing or has zero size. */ ++ ++ cupsFileClose(*lf); ++ if ((*lf = cupsFileOpen(filename, "a")) == NULL) ++ { ++ syslog(LOG_ERR, "Unable to open log file "%s" - %s", filename, ++ strerror(errno)); ++ ++ return (0); ++ } ++ ++ /* ++ * Change ownership and permissions of non-device logs... ++ */ ++ ++ fchown(cupsFileNumber(*lf), RunUser, Group); ++ fchmod(cupsFileNumber(*lf), LogFilePerm); ++ } ++ } ++ ++ /* + * Do we need to rotate the log? + */ + diff --git a/pkgs/core/cups/patches/cups-lpr-help.patch b/pkgs/core/cups/patches/cups-lpr-help.patch new file mode 100644 index 0000000..1a68297 --- /dev/null +++ b/pkgs/core/cups/patches/cups-lpr-help.patch @@ -0,0 +1,56 @@ +diff -up cups-1.4b1/berkeley/lpr.c.lpr-help cups-1.4b1/berkeley/lpr.c +--- cups-1.4b1/berkeley/lpr.c.lpr-help 2008-07-11 23:46:21.000000000 +0100 ++++ cups-1.4b1/berkeley/lpr.c 2008-11-11 16:20:32.000000000 +0000 +@@ -30,6 +30,31 @@ + #include <cups/i18n.h> + + ++static void ++usage (const char *name) ++{ ++ _cupsLangPrintf(stdout, ++"Usage: %s [OPTION] [ file(s) ]\n" ++"Print files.\n\n" ++" -E force encryption\n" ++" -H server[:port] specify alternate server\n" ++" -C title, -J title, -T title\n" ++" set the job name\n\n" ++" -P destination/instance print to named printer\n" ++" -U username specify alternate username\n" ++" -# num-copies set number of copies\n" ++" -h disable banner printing\n" ++" -l print without filtering\n" ++" -m send email on completion\n" ++" -o option[=value] set a job option\n" ++" -p format text file with header\n" ++" -q hold job for printing\n" ++" -r delete files after printing\n" ++"\nWith no file given, read standard input.\n" ++, name); ++} ++ ++ + /* + * 'main()' - Parse options and send files for printing. + */ +@@ -54,7 +79,6 @@ main(int argc, /* I - Number of comm + int deletefile; /* Delete file after print? */ + char buffer[8192]; /* Copy buffer */ + +- + _cupsSetLocale(argv); + + deletefile = 0; +@@ -282,6 +306,12 @@ main(int argc, /* I - Number of comm + break; + + default : ++ if (!strcmp (argv[i], "--help")) ++ { ++ usage (argv[0]); ++ return (0); ++ } ++ + _cupsLangPrintf(stderr, + _("%s: Error - unknown option '%c'!\n"), + argv[0], argv[i][1]); diff --git a/pkgs/core/cups/patches/cups-multilib.patch b/pkgs/core/cups/patches/cups-multilib.patch new file mode 100644 index 0000000..21db4cb --- /dev/null +++ b/pkgs/core/cups/patches/cups-multilib.patch @@ -0,0 +1,15 @@ +--- cups-1.2.3/cups-config.in.multilib 2006-08-03 01:54:38.000000000 +0100 ++++ cups-1.2.3/cups-config.in 2006-08-30 15:47:35.000000000 +0100 +@@ -30,8 +30,10 @@ + exec_prefix=@exec_prefix@ + bindir=@bindir@ + includedir=@includedir@ +-libdir=@libdir@ +-imagelibdir=@libdir@ ++# Fetch libdir from gnutls's pkg-config script. This is a bit ++# of a cheat, but the cups-devel package requires gnutls-devel anyway. ++libdir=`pkg-config --variable=libdir gnutls` ++imagelibdir=`pkg-config --variable=libdir gnutls` + datarootdir=@datadir@ + datadir=@datadir@ + sysconfdir=@sysconfdir@ diff --git a/pkgs/core/cups/patches/cups-no-export-ssllibs.patch b/pkgs/core/cups/patches/cups-no-export-ssllibs.patch new file mode 100644 index 0000000..9effc8e --- /dev/null +++ b/pkgs/core/cups/patches/cups-no-export-ssllibs.patch @@ -0,0 +1,12 @@ +diff -up cups-1.4b2-svn8404/config-scripts/cups-ssl.m4.no-export-ssllibs cups-1.4b2-svn8404/config-scripts/cups-ssl.m4 +--- cups-1.4b2-svn8404/config-scripts/cups-ssl.m4.no-export-ssllibs 2009-02-17 17:45:27.000000000 +0000 ++++ cups-1.4b2-svn8404/config-scripts/cups-ssl.m4 2009-03-05 11:12:59.000000000 +0000 +@@ -110,7 +110,7 @@ fi + AC_SUBST(SSLFLAGS) + AC_SUBST(SSLLIBS) + +-EXPORT_SSLLIBS="$SSLLIBS" ++EXPORT_SSLLIBS="" + AC_SUBST(EXPORT_SSLLIBS) + + diff --git a/pkgs/core/cups/patches/cups-no-gzip-man.patch b/pkgs/core/cups/patches/cups-no-gzip-man.patch new file mode 100644 index 0000000..4a08503 --- /dev/null +++ b/pkgs/core/cups/patches/cups-no-gzip-man.patch @@ -0,0 +1,18 @@ +diff -up cups-1.4b2-svn8404/config-scripts/cups-manpages.m4.no-gzip-man cups-1.4b2-svn8404/config-scripts/cups-manpages.m4 +--- cups-1.4b2-svn8404/config-scripts/cups-manpages.m4.no-gzip-man 2009-01-16 08:58:42.000000000 +0000 ++++ cups-1.4b2-svn8404/config-scripts/cups-manpages.m4 2009-03-05 11:11:12.000000000 +0000 +@@ -69,10 +69,10 @@ case "$uname" in + ;; + Linux* | GNU* | Darwin*) + # Linux, GNU Hurd, and Mac OS X +- MAN1EXT=1.gz +- MAN5EXT=5.gz +- MAN7EXT=7.gz +- MAN8EXT=8.gz ++ MAN1EXT=1 ++ MAN5EXT=5 ++ MAN7EXT=7 ++ MAN8EXT=8 + MAN8DIR=8 + ;; + *) diff --git a/pkgs/core/cups/patches/cups-page-label.patch b/pkgs/core/cups/patches/cups-page-label.patch new file mode 100644 index 0000000..220b31d --- /dev/null +++ b/pkgs/core/cups/patches/cups-page-label.patch @@ -0,0 +1,92 @@ +diff -up cups-1.4.5/filter/pstops.c.page-label cups-1.4.5/filter/pstops.c +--- cups-1.4.5/filter/pstops.c.page-label 2010-08-31 20:36:08.000000000 +0200 ++++ cups-1.4.5/filter/pstops.c 2010-11-12 13:11:11.000000000 +0100 +@@ -108,6 +108,7 @@ typedef struct /**** Document informa + int num_options; /* Number of document-wide options */ + cups_option_t *options; /* Document-wide options */ + int normal_landscape, /* Normal rotation for landscape? */ ++ orientation, /* Original orientation of the document */ + saw_eof, /* Saw the %%EOF comment? */ + slow_collate, /* Collate copies by hand? */ + slow_duplex, /* Duplex pages slowly? */ +@@ -2083,7 +2084,7 @@ do_setup(pstops_doc_t *doc, /* I - Docu + * of the pages... + */ + +- if (Orientation & 1) ++ if (doc->orientation & 1) + write_label_prolog(doc, doc->page_label, PageBottom, + PageWidth - PageLength + PageTop, PageLength); + else +@@ -2091,7 +2092,30 @@ do_setup(pstops_doc_t *doc, /* I - Docu + PageLength); + } + else +- write_label_prolog(doc, doc->page_label, PageBottom, PageTop, PageWidth); ++ { ++ switch (doc->orientation) ++ { ++ case 0 : ++ write_label_prolog(doc, doc->page_label, PageBottom, PageTop, ++ PageWidth); ++ break; ++ ++ case 1 : ++ write_label_prolog(doc, doc->page_label, PageLeft, PageRight, ++ PageLength); ++ break; ++ ++ case 2 : ++ write_label_prolog(doc, doc->page_label, PageLength - PageTop, ++ PageLength - PageBottom, PageWidth); ++ break; ++ ++ case 3 : ++ write_label_prolog(doc, doc->page_label, PageWidth - PageRight, ++ PageWidth - PageLeft, PageLength); ++ break; ++ } ++ } + } + + +@@ -2176,7 +2200,7 @@ end_nup(pstops_doc_t *doc, /* I - Docum + case 1 : + if (doc->use_ESPshowpage) + { +- write_labels(doc, Orientation); ++ write_labels(doc, doc->orientation); + doc_puts(doc, "ESPshowpage\n"); + } + break; +@@ -2191,7 +2215,7 @@ end_nup(pstops_doc_t *doc, /* I - Docum + * Rotate the labels back to portrait... + */ + +- write_labels(doc, Orientation - 1); ++ write_labels(doc, doc->orientation - 1); + } + else if (Orientation == 0) + { +@@ -2217,7 +2241,7 @@ end_nup(pstops_doc_t *doc, /* I - Docum + default : + if (is_last_page(number) && doc->use_ESPshowpage) + { +- write_labels(doc, Orientation); ++ write_labels(doc, doc->orientation); + doc_puts(doc, "ESPshowpage\n"); + } + break; +@@ -2433,6 +2457,12 @@ set_pstops_options( + Orientation = 0; + + /* ++ * Save original orientation of the document ++ */ ++ ++ doc->orientation = Orientation; ++ ++ /* + * AP_FIRSTPAGE_* and the corresponding non-first-page options. + */ + diff --git a/pkgs/core/cups/patches/cups-peercred.patch b/pkgs/core/cups/patches/cups-peercred.patch new file mode 100644 index 0000000..4e579b4 --- /dev/null +++ b/pkgs/core/cups/patches/cups-peercred.patch @@ -0,0 +1,11 @@ +diff -up cups-1.3.5/scheduler/auth.c.peercred cups-1.3.5/scheduler/auth.c +--- cups-1.3.5/scheduler/auth.c.peercred 2008-02-05 16:52:20.000000000 +0000 ++++ cups-1.3.5/scheduler/auth.c 2008-02-05 18:20:06.000000000 +0000 +@@ -54,6 +54,7 @@ + * Include necessary headers... + */ + ++#define _GNU_SOURCE + #include "cupsd.h" + #include <grp.h> + #ifdef HAVE_SHADOW_H diff --git a/pkgs/core/cups/patches/cups-pid.patch b/pkgs/core/cups/patches/cups-pid.patch new file mode 100644 index 0000000..ab4ff84 --- /dev/null +++ b/pkgs/core/cups/patches/cups-pid.patch @@ -0,0 +1,36 @@ +--- cups-1.1.21/scheduler/main.c.pid 2004-09-24 11:29:05.073748138 +0100 ++++ cups-1.1.21/scheduler/main.c 2004-09-24 11:44:35.826446564 +0100 +@@ -349,6 +349,8 @@ + * Setup signal handlers for the parent... + */ + ++ pid_t pid; ++ + #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGUSR1, parent_handler); + sigset(SIGCHLD, parent_handler); +@@ -372,7 +374,7 @@ + signal(SIGHUP, SIG_IGN); + #endif /* HAVE_SIGSET */ + +- if (fork() > 0) ++ if ((pid = fork()) > 0) + { + /* + * OK, wait for the child to startup and send us SIGUSR1 or to crash +@@ -384,7 +386,15 @@ + sleep(1); + + if (parent_signal == SIGUSR1) ++ { ++ FILE *f = fopen ("/var/run/cupsd.pid", "w"); ++ if (f) ++ { ++ fprintf (f, "%d\n", pid); ++ fclose (f); ++ } + return (0); ++ } + + if (wait(&i) < 0) + { diff --git a/pkgs/core/cups/patches/cups-res_init.patch b/pkgs/core/cups/patches/cups-res_init.patch new file mode 100644 index 0000000..22c75ba --- /dev/null +++ b/pkgs/core/cups/patches/cups-res_init.patch @@ -0,0 +1,12 @@ +diff -up cups-1.4b2-svn8404/cups/http-addrlist.c.res_init cups-1.4b2-svn8404/cups/http-addrlist.c +--- cups-1.4b2-svn8404/cups/http-addrlist.c.res_init 2009-03-23 17:41:03.000000000 +0000 ++++ cups-1.4b2-svn8404/cups/http-addrlist.c 2009-03-23 17:41:26.000000000 +0000 +@@ -373,7 +373,7 @@ httpAddrGetList(const char *hostname, /* + + freeaddrinfo(results); + } +- else if (error == EAI_FAIL) ++ else if (error == EAI_FAIL || error == EAI_AGAIN || error == EAI_NODATA) + cg->need_res_init = 1; + + #else diff --git a/pkgs/core/cups/patches/cups-ricoh-deviceid-oid.patch b/pkgs/core/cups/patches/cups-ricoh-deviceid-oid.patch new file mode 100644 index 0000000..6a5b6a9 --- /dev/null +++ b/pkgs/core/cups/patches/cups-ricoh-deviceid-oid.patch @@ -0,0 +1,21 @@ +diff -up cups-1.4.3/backend/snmp.c.ricoh-deviceid-oid cups-1.4.3/backend/snmp.c +--- cups-1.4.3/backend/snmp.c.ricoh-deviceid-oid 2010-05-11 17:30:57.266120467 +0100 ++++ cups-1.4.3/backend/snmp.c 2010-05-11 17:31:16.267120141 +0100 +@@ -195,6 +195,7 @@ static const int LexmarkProductOID[] = { + static const int LexmarkProductOID2[] = { 1,3,6,1,4,1,674,10898,100,2,1,2,1,2,1,-1 }; + static const int LexmarkDeviceIdOID[] = { 1,3,6,1,4,1,641,2,1,2,1,3,1,-1 }; + static const int HPDeviceIdOID[] = { 1,3,6,1,4,1,11,2,3,9,1,1,7,0,-1 }; ++static const int RicohDeviceIdOID[] = { 1,3,6,1,4,1,367,3,2,1,1,1,11,0,-1 }; + static const int XeroxProductOID[] = { 1,3,6,1,4,1,128,2,1,3,1,2,0,-1 }; + static cups_array_t *DeviceURIs = NULL; + static int HostNameLookups = 0; +@@ -1002,6 +1003,9 @@ read_snmp_response(int fd) /* I - SNMP + packet.community, CUPS_ASN1_GET_REQUEST, + DEVICE_ID, LexmarkDeviceIdOID); + _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, ++ packet.community, CUPS_ASN1_GET_REQUEST, ++ DEVICE_ID, RicohDeviceIdOID); ++ _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, + packet.community, CUPS_ASN1_GET_REQUEST, + DEVICE_PRODUCT, XeroxProductOID); + _cupsSNMPWrite(fd, &(packet.address), CUPS_SNMP_VERSION_1, diff --git a/pkgs/core/cups/patches/cups-serial.patch b/pkgs/core/cups/patches/cups-serial.patch new file mode 100644 index 0000000..6e111f2 --- /dev/null +++ b/pkgs/core/cups/patches/cups-serial.patch @@ -0,0 +1,11 @@ +diff -up cups-1.4b2/backend/serial.c.serial cups-1.4b2/backend/serial.c +--- cups-1.4b2/backend/serial.c.serial 2008-12-16 16:25:02.000000000 +0000 ++++ cups-1.4b2/backend/serial.c 2008-12-16 16:25:21.000000000 +0000 +@@ -74,6 +74,7 @@ + #endif /* __APPLE__ */ + + #if defined(__linux) && defined(TIOCGSERIAL) ++# include <linux/types.h> + # include <linux/serial.h> + # include <linux/ioctl.h> + #endif /* __linux && TIOCGSERIAL */ diff --git a/pkgs/core/cups/patches/cups-serialize-gnutls.patch b/pkgs/core/cups/patches/cups-serialize-gnutls.patch new file mode 100644 index 0000000..cdd82cb --- /dev/null +++ b/pkgs/core/cups/patches/cups-serialize-gnutls.patch @@ -0,0 +1,109 @@ +diff -up cups-1.4.4/cups/http.c.serialize-gnutls cups-1.4.4/cups/http.c +--- cups-1.4.4/cups/http.c.serialize-gnutls 2010-09-17 13:37:01.858871762 +0100 ++++ cups-1.4.4/cups/http.c 2010-09-17 13:55:22.579871934 +0100 +@@ -149,7 +149,7 @@ static int http_write_ssl(http_t *http, + + # ifdef HAVE_GNUTLS + # ifdef HAVE_PTHREAD_H +-GCRY_THREAD_OPTION_PTHREAD_IMPL; ++static pthread_mutex_t gnutls_lock; + # endif /* HAVE_PTHREAD_H */ + + # elif defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD_H) +@@ -1231,7 +1231,7 @@ httpInitialize(void) + */ + + # ifdef HAVE_PTHREAD_H +- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); ++ pthread_mutex_init(&gnutls_lock, NULL); + # endif /* HAVE_PTHREAD_H */ + + /* +@@ -2228,6 +2228,7 @@ _httpWait(http_t *http, /* I - Connect + if (SSL_pending((SSL *)(http->tls))) + return (1); + # elif defined(HAVE_GNUTLS) ++ /* lock already held here... */ + if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session)) + return (1); + # elif defined(HAVE_CDSASSL) +@@ -2294,6 +2295,8 @@ int /* O - 1 if data is available, 0 + httpWait(http_t *http, /* I - Connection to server */ + int msec) /* I - Milliseconds to wait */ + { ++ int ret; ++ + /* + * First see if there is data in the buffer... + */ +@@ -2318,7 +2321,17 @@ httpWait(http_t *http, /* I - Connecti + * If not, check the SSL/TLS buffers and do a select() on the connection... + */ + +- return (_httpWait(http, msec, 1)); ++#if defined(HAVE_SSL) && defined(HAVE_GNUTLS) && defined(HAVE_PTHREAD_H) ++ pthread_mutex_lock(&gnutls_lock); ++#endif ++ ++ ret = _httpWait(http, msec, 1); ++ ++#if defined(HAVE_SSL) && defined(HAVE_GNUTLS) && defined(HAVE_PTHREAD_H) ++ pthread_mutex_unlock(&gnutls_lock); ++#endif ++ ++ return (ret); + } + + +@@ -2769,7 +2782,9 @@ http_read_ssl(http_t *http, /* I - Conn + ssize_t result; /* Return value */ + + ++ pthread_mutex_lock(&gnutls_lock); + result = gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len); ++ pthread_mutex_unlock(&gnutls_lock); + + if (result < 0 && !errno) + { +@@ -3085,6 +3100,7 @@ http_setup_ssl(http_t *http) /* I - Con + return (-1); + } + ++ pthread_mutex_lock(&gnutls_lock); + gnutls_certificate_allocate_credentials(credentials); + + gnutls_init(&(conn->session), GNUTLS_CLIENT); +@@ -3104,9 +3120,11 @@ http_setup_ssl(http_t *http) /* I - Con + free(credentials); + free(conn); + ++ pthread_mutex_unlock(&gnutls_lock); + return (-1); + } + ++ pthread_mutex_unlock(&gnutls_lock); + conn->credentials = credentials; + + # elif defined(HAVE_CDSASSL) +@@ -3196,9 +3214,11 @@ http_shutdown_ssl(http_t *http) /* I - + conn = (http_tls_t *)(http->tls); + credentials = (gnutls_certificate_client_credentials *)(conn->credentials); + ++ pthread_mutex_lock(&gnutls_lock); + gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); + gnutls_deinit(conn->session); + gnutls_certificate_free_credentials(*credentials); ++ pthread_mutex_unlock(&gnutls_lock); + free(credentials); + free(conn); + +@@ -3445,7 +3465,9 @@ http_write_ssl(http_t *http, /* I - + # elif defined(HAVE_GNUTLS) + ssize_t result; /* Return value */ + ++ pthread_mutex_lock(&gnutls_lock); + result = gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len); ++ pthread_mutex_unlock(&gnutls_lock); + + if (result < 0 && !errno) + { diff --git a/pkgs/core/cups/patches/cups-serverbin-compat.patch b/pkgs/core/cups/patches/cups-serverbin-compat.patch new file mode 100644 index 0000000..44a7894 --- /dev/null +++ b/pkgs/core/cups/patches/cups-serverbin-compat.patch @@ -0,0 +1,194 @@ +diff -up cups-1.4.4/scheduler/conf.c.serverbin-compat cups-1.4.4/scheduler/conf.c +--- cups-1.4.4/scheduler/conf.c.serverbin-compat 2010-04-23 19:56:34.000000000 +0100 ++++ cups-1.4.4/scheduler/conf.c 2010-09-15 13:20:41.339960335 +0100 +@@ -488,6 +488,9 @@ cupsdReadConfiguration(void) + cupsdClearString(&ServerName); + cupsdClearString(&ServerAdmin); + cupsdSetString(&ServerBin, CUPS_SERVERBIN); ++#ifdef __x86_64__ ++ cupsdSetString(&ServerBin_compat, "/usr/lib64/cups"); ++#endif /* __x86_64__ */ + cupsdSetString(&RequestRoot, CUPS_REQUESTS); + cupsdSetString(&CacheDir, CUPS_CACHEDIR); + cupsdSetString(&DataDir, CUPS_DATADIR); +@@ -1318,7 +1321,12 @@ cupsdReadConfiguration(void) + * Read the MIME type and conversion database... + */ + ++#ifdef __x86_64__ ++ snprintf(temp, sizeof(temp), "%s/filter:%s/filter", ServerBin, ++ ServerBin_compat); ++#else + snprintf(temp, sizeof(temp), "%s/filter", ServerBin); ++#endif + snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir); + + MimeDatabase = mimeLoadTypes(NULL, mimedir); +diff -up cups-1.4.4/scheduler/conf.h.serverbin-compat cups-1.4.4/scheduler/conf.h +--- cups-1.4.4/scheduler/conf.h.serverbin-compat 2010-04-23 19:56:34.000000000 +0100 ++++ cups-1.4.4/scheduler/conf.h 2010-09-15 13:20:41.340959464 +0100 +@@ -105,6 +105,10 @@ VAR char *ConfigurationFile VALUE(NULL) + /* Root directory for scheduler */ + *ServerBin VALUE(NULL), + /* Root directory for binaries */ ++#ifdef __x86_64__ ++ *ServerBin_compat VALUE(NULL), ++ /* Compat directory for binaries */ ++#endif /* __x86_64__ */ + *StateDir VALUE(NULL), + /* Root directory for state data */ + *RequestRoot VALUE(NULL), +diff -up cups-1.4.4/scheduler/env.c.serverbin-compat cups-1.4.4/scheduler/env.c +--- cups-1.4.4/scheduler/env.c.serverbin-compat 2009-06-15 18:13:52.000000000 +0100 ++++ cups-1.4.4/scheduler/env.c 2010-09-15 13:20:41.341959587 +0100 +@@ -87,8 +87,13 @@ cupsdInitEnv(void) + cupsdSetEnv("LD_LIBRARY_PATH", NULL); + cupsdSetEnv("LD_PRELOAD", NULL); + cupsdSetEnv("NLSPATH", NULL); ++#ifdef __x86_64__ ++ cupsdSetEnvf("PATH", "%s/filter:%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ++ ":/bin:/usr/bin", ServerBin, ServerBin_compat); ++#else /* ! defined(__x86_64__) */ + cupsdSetEnvf("PATH", "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR + ":/bin:/usr/bin", ServerBin); ++#endif + cupsdSetEnv("SERVER_ADMIN", ServerAdmin); + cupsdSetEnv("SHLIB_PATH", NULL); + cupsdSetEnv("SOFTWARE", CUPS_MINIMAL); +diff -up cups-1.4.4/scheduler/ipp.c.serverbin-compat cups-1.4.4/scheduler/ipp.c +--- cups-1.4.4/scheduler/ipp.c.serverbin-compat 2010-04-23 19:56:34.000000000 +0100 ++++ cups-1.4.4/scheduler/ipp.c 2010-09-15 13:20:41.359835378 +0100 +@@ -2615,9 +2615,18 @@ add_printer(cupsd_client_t *con, /* I - + * Could not find device in list! + */ + ++#ifdef __x86_64__ ++ snprintf(srcfile, sizeof(srcfile), "%s/backend/%s", ServerBin_compat, ++ scheme); ++ if (access(srcfile, X_OK)) ++ { ++#endif /* __x86_64__ */ + send_ipp_status(con, IPP_NOT_POSSIBLE, _("Bad device-uri scheme "%s"!"), + scheme); + return; ++#ifdef __x86_64__ ++ } ++#endif /* __x86_64__ */ + } + } + +diff -up cups-1.4.4/scheduler/job.c.serverbin-compat cups-1.4.4/scheduler/job.c +--- cups-1.4.4/scheduler/job.c.serverbin-compat 2010-03-30 23:07:33.000000000 +0100 ++++ cups-1.4.4/scheduler/job.c 2010-09-15 13:20:41.366836134 +0100 +@@ -972,8 +972,32 @@ cupsdContinueJob(cupsd_job_t *job) /* I + i ++, filter = (mime_filter_t *)cupsArrayNext(filters)) + { + if (filter->filter[0] != '/') +- snprintf(command, sizeof(command), "%s/filter/%s", ServerBin, +- filter->filter); ++ { ++ snprintf(command, sizeof(command), "%s/filter/%s", ServerBin, ++ filter->filter); ++#ifdef __x86_64__ ++ if (access(command, F_OK)) ++ { ++ snprintf(command, sizeof(command), "%s/filter/%s", ++ ServerBin_compat, filter->filter); ++ if (!access(command, F_OK)) ++ { ++ /* Not in the correct directory, but found it in the compat ++ * directory. Issue a warning. */ ++ cupsdLogMessage(CUPSD_LOG_INFO, ++ "Filter '%s' not in %s/filter!", ++ filter->filter, ServerBin); ++ } ++ else ++ { ++ /* Not in the compat directory either; make any error ++ * messages use the correct directory name then. */ ++ snprintf(command, sizeof(command), "%s/filter/%s", ServerBin, ++ filter->filter); ++ } ++ } ++#endif /* __x86_64__ */ ++ } + else + strlcpy(command, filter->filter, sizeof(command)); + +@@ -1119,6 +1143,28 @@ cupsdContinueJob(cupsd_job_t *job) /* I + cupsdClosePipe(job->print_pipes); + cupsdClosePipe(job->back_pipes); + cupsdClosePipe(job->side_pipes); ++#ifdef __x86_64__ ++ if (access(command, F_OK)) ++ { ++ snprintf(command, sizeof(command), "%s/backend/%s", ServerBin_compat, ++ method); ++ if (!access(command, F_OK)) ++ { ++ /* Not in the correct directory, but we found it in the compat ++ * directory. Issue a warning. */ ++ cupsdLogMessage(CUPSD_LOG_INFO, ++ "Backend '%s' not in %s/backend!", method, ++ ServerBin); ++ } ++ else ++ { ++ /* Not in the compat directory either; make any error ++ messages use the correct directory name then. */ ++ snprintf(command, sizeof(command), "%s/backend/%s", ServerBin, ++ method); ++ } ++ } ++#endif /* __x86_64__ */ + + close(job->status_pipes[1]); + job->status_pipes[1] = -1; +diff -up cups-1.4.4/scheduler/printers.c.serverbin-compat cups-1.4.4/scheduler/printers.c +--- cups-1.4.4/scheduler/printers.c.serverbin-compat 2010-04-23 21:53:38.000000000 +0100 ++++ cups-1.4.4/scheduler/printers.c 2010-09-15 13:21:39.627960657 +0100 +@@ -1059,9 +1059,19 @@ cupsdLoadAllPrinters(void) + * Backend does not exist, stop printer... + */ + ++#ifdef __x86_64__ ++ snprintf(line, sizeof(line), "%s/backend/%s", ServerBin_compat, ++ p->device_uri); ++ if (access(line, 0)) ++ { ++#endif /* __x86_64__ */ ++ + p->state = IPP_PRINTER_STOPPED; + snprintf(p->state_message, sizeof(p->state_message), + "Backend %s does not exist!", line); ++#ifdef __x86_64__ ++ } ++#endif /* __x86_64__ */ + } + } + +@@ -3603,6 +3613,14 @@ add_printer_filter( + + if (stat(filename, &fileinfo)) + { ++#ifdef __x86_64__ ++ snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin_compat, ++ program); ++ if (stat(filename, &fileinfo)) ++ { ++ snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, ++ program); ++#endif /* __x86_64__ */ + memset(&fileinfo, 0, sizeof(fileinfo)); + + snprintf(p->state_message, sizeof(p->state_message), +@@ -3611,6 +3629,9 @@ add_printer_filter( + cupsdSetPrinterReasons(p, "+cups-missing-filter-warning"); + + cupsdLogMessage(CUPSD_LOG_ERROR, "%s", p->state_message); ++#ifdef __x86_64__ ++ } ++#endif /* __x86_64__ */ + } + + /* diff --git a/pkgs/core/cups/patches/cups-snmp-quirks.patch b/pkgs/core/cups/patches/cups-snmp-quirks.patch new file mode 100644 index 0000000..0308676 --- /dev/null +++ b/pkgs/core/cups/patches/cups-snmp-quirks.patch @@ -0,0 +1,115 @@ +diff -up cups-1.4.3/backend/snmp-supplies.c.snmp-quirks cups-1.4.3/backend/snmp-supplies.c +--- cups-1.4.3/backend/snmp-supplies.c.snmp-quirks 2009-11-20 01:27:57.000000000 +0000 ++++ cups-1.4.3/backend/snmp-supplies.c 2010-06-09 16:27:05.515019804 +0100 +@@ -38,6 +38,13 @@ + + + /* ++ * Printer quirks... ++ */ ++ ++#define QUIRK_CAPACITY (1<<0) ++ ++ ++/* + * Local structures... + */ + +@@ -57,6 +64,12 @@ typedef struct /**** Printer state ta + const char *keyword; /* IPP printer-state-reasons keyword */ + } backend_state_t; + ++typedef struct /**** Quirk names table ****/ ++{ ++ int bit; /* Quirk bit */ ++ const char *keyword; /* cupsSNMPQuirks keyword */ ++} quirk_name_t; ++ + + /* + * Local globals... +@@ -68,6 +81,7 @@ static int current_state = -1; + static int charset = -1; /* Character set for supply names */ + static int num_supplies = 0; + /* Number of supplies found */ ++static int quirks = 0; /* Printer quirks */ + static backend_supplies_t supplies[CUPS_MAX_SUPPLIES]; + /* Supply information */ + +@@ -153,6 +167,15 @@ static const backend_state_t const print + { CUPS_TC_outputFull, "output-area-full-warning" } + }; + ++static const quirk_name_t const quirk_names[] = ++ { ++ /* ++ * The prtMarkerSuppliesLevel values are ++ * percentages, not levels relative to the ++ * stated capacity. ++ */ ++ { QUIRK_CAPACITY, "capacity" } ++ }; + + /* + * Local functions... +@@ -208,6 +231,9 @@ backendSNMPSupplies( + if (i) + *ptr++ = ','; + ++ if (quirks & QUIRK_CAPACITY) ++ supplies[i].max_capacity = 100; ++ + if (supplies[i].max_capacity > 0) + sprintf(ptr, "%d", 100 * supplies[i].level / supplies[i].max_capacity); + else +@@ -305,6 +331,7 @@ backend_init_supplies( + http_addr_t *addr) /* I - Printer address */ + { + int i, /* Looping var */ ++ len, /* Quirk name length */ + type; /* Current marker type */ + cups_file_t *cachefile; /* Cache file */ + const char *cachedir; /* CUPS_CACHEDIR value */ +@@ -366,6 +393,7 @@ backend_init_supplies( + current_state = -1; + num_supplies = -1; + charset = -1; ++ quirks = 0; + + memset(supplies, 0, sizeof(supplies)); + +@@ -381,6 +409,34 @@ backend_init_supplies( + return; + } + ++ if (ppd && ++ (ppdattr = ppdFindAttr(ppd, "cupsSNMPQuirks", NULL)) != NULL && ++ ppdattr->value) ++ { ++ ptr = ppdattr->value; ++ while (*ptr != '\0') ++ { ++ /* ++ * Match keyword against quirk_names table. ++ */ ++ ++ for (i = 0; i < sizeof (quirk_names) / sizeof (quirk_names[0]); i++) ++ { ++ len = strlen (quirk_names[i].keyword); ++ if (!strncmp (ptr, quirk_names[i].keyword, len) && ++ (ptr[len] == '\0' || ptr[len] == ' ')) ++ quirks |= quirk_names[i].bit; ++ } ++ ++ /* ++ * Advance to next keyword. ++ */ ++ ++ ptr += strcspn (ptr, " "); ++ ptr += strspn (ptr, " "); ++ } ++ } ++ + ppdClose(ppd); + + /* diff --git a/pkgs/core/cups/patches/cups-str3382.patch b/pkgs/core/cups/patches/cups-str3382.patch new file mode 100644 index 0000000..14e9b27 --- /dev/null +++ b/pkgs/core/cups/patches/cups-str3382.patch @@ -0,0 +1,64 @@ +diff -up cups-1.4.3/cups/tempfile.c.str3382 cups-1.4.3/cups/tempfile.c +--- cups-1.4.3/cups/tempfile.c.str3382 2010-01-18 19:47:12.000000000 +0100 ++++ cups-1.4.3/cups/tempfile.c 2010-03-31 13:26:52.000000000 +0200 +@@ -35,6 +35,7 @@ + # include <io.h> + #else + # include <unistd.h> ++# include <sys/types.h> + #endif /* WIN32 || __EMX__ */ + + +@@ -56,7 +57,7 @@ cupsTempFd(char *filename, /* I - Point + char tmppath[1024]; /* Windows temporary directory */ + DWORD curtime; /* Current time */ + #else +- struct timeval curtime; /* Current time */ ++ mode_t old_umask; /* Old umask before using mkstemp() */ + #endif /* WIN32 */ + + +@@ -107,33 +108,25 @@ cupsTempFd(char *filename, /* I - Point + + snprintf(filename, len - 1, "%s/%05lx%08lx", tmpdir, + GetCurrentProcessId(), curtime); +-#else +- /* +- * Get the current time of day... +- */ +- +- gettimeofday(&curtime, NULL); +- +- /* +- * Format a string using the hex time values... +- */ +- +- snprintf(filename, len - 1, "%s/%05x%08x", tmpdir, (unsigned)getpid(), +- (unsigned)(curtime.tv_sec + curtime.tv_usec + tries)); +-#endif /* WIN32 */ + + /* + * Open the file in "exclusive" mode, making sure that we don't + * stomp on an existing file or someone's symlink crack... + */ + +-#ifdef WIN32 + fd = open(filename, _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY, + _S_IREAD | _S_IWRITE); +-#elif defined(O_NOFOLLOW) +- fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); + #else +- fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); ++ ++ /* ++ * Use the standard mkstemp() call to make a temporary filename ++ * securely. -- andrew.wood@jdplc.com ++ */ ++ snprintf(filename, len - 1, "%s/cupsXXXXXX", tmpdir); ++ ++ old_umask = umask(0077); ++ fd = mkstemp(filename); ++ umask(old_umask); + #endif /* WIN32 */ + + if (fd < 0 && errno != EEXIST) diff --git a/pkgs/core/cups/patches/cups-str3754.patch b/pkgs/core/cups/patches/cups-str3754.patch new file mode 100644 index 0000000..148575a --- /dev/null +++ b/pkgs/core/cups/patches/cups-str3754.patch @@ -0,0 +1,11 @@ +diff -up cups-1.4.5/scheduler/printers.c.printer-timeout cups-1.4.5/scheduler/printers.c +--- cups-1.4.5/scheduler/printers.c.printer-timeout 2010-12-16 14:42:07.048865052 +0000 ++++ cups-1.4.5/scheduler/printers.c 2010-12-16 14:43:05.325684376 +0000 +@@ -785,6 +785,7 @@ cupsdDeletePrinter( + */ + + cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, update); ++ p->state = IPP_PRINTER_STOPPED; + + if (p->job) + cupsdSetJobState(p->job, IPP_JOB_PENDING, CUPSD_JOB_FORCE, diff --git a/pkgs/core/cups/patches/cups-strict-ppd-line-length.patch b/pkgs/core/cups/patches/cups-strict-ppd-line-length.patch new file mode 100644 index 0000000..d393728 --- /dev/null +++ b/pkgs/core/cups/patches/cups-strict-ppd-line-length.patch @@ -0,0 +1,30 @@ +diff -up cups-1.3.5/cups/ppd.c~ cups-1.3.5/cups/ppd.c +--- cups-1.3.5/cups/ppd.c~ 2007-11-30 19:29:50.000000000 +0000 ++++ cups-1.3.5/cups/ppd.c 2008-01-09 12:08:48.000000000 +0000 +@@ -2801,7 +2801,7 @@ ppd_read(cups_file_t *fp, /* I - Fil + *lineptr++ = ch; + col ++; + +- if (col > (PPD_MAX_LINE - 1)) ++ if (col > (PPD_MAX_LINE - 1) && cg->ppd_conform == PPD_CONFORM_STRICT) + { + /* + * Line is too long... +@@ -2868,7 +2868,7 @@ ppd_read(cups_file_t *fp, /* I - Fil + { + col ++; + +- if (col > (PPD_MAX_LINE - 1)) ++ if (col > (PPD_MAX_LINE - 1) && cg->ppd_conform == PPD_CONFORM_STRICT) + { + /* + * Line is too long... +@@ -2931,7 +2931,7 @@ ppd_read(cups_file_t *fp, /* I - Fil + { + col ++; + +- if (col > (PPD_MAX_LINE - 1)) ++ if (col > (PPD_MAX_LINE - 1) && cg->ppd_conform == PPD_CONFORM_STRICT) + { + /* + * Line is too long... diff --git a/pkgs/core/cups/patches/cups-texttops-rotate-page.patch b/pkgs/core/cups/patches/cups-texttops-rotate-page.patch new file mode 100644 index 0000000..2b048cd --- /dev/null +++ b/pkgs/core/cups/patches/cups-texttops-rotate-page.patch @@ -0,0 +1,35 @@ +diff -up cups-1.4.3/filter/texttops.c.texttops-rotate-page cups-1.4.3/filter/texttops.c +--- cups-1.4.3/filter/texttops.c.texttops-rotate-page 2008-11-06 16:42:18.000000000 +0000 ++++ cups-1.4.3/filter/texttops.c 2010-05-18 16:42:23.669940884 +0100 +@@ -97,6 +97,13 @@ WritePage(void) + + puts("gsave"); + ++ /* If we're opereating in Landscape (Orientation == 1 or Orientation == 3) ++ then rotate and translate the page */ ++ if ( Orientation & 1 ) { ++ printf ("%d rotate\n", (Orientation & 3) * 90 ); ++ printf("0 %.0f neg translate\n", PageLength); ++ } ++ + if (PrettyPrint) + printf("%d H\n", NumPages); + +@@ -212,7 +219,7 @@ WriteProlog(const char *title, /* I - T + + puts("%!PS-Adobe-3.0"); + printf("%%%%BoundingBox: 0 0 %.0f %.0f\n", PageWidth, PageLength); +- printf("%%cupsRotation: %d\n", (Orientation & 3) * 90); ++ puts("%cupsRotation: 0"); + puts("%%Creator: texttops/" CUPS_SVERSION); + printf("%%%%CreationDate: %s\n", curdate); + WriteTextComment("Title", title); +@@ -549,6 +556,8 @@ WriteProlog(const char *title, /* I - T + puts("%%EndComments"); + + puts("%%BeginProlog"); ++ printf("%%%%Orientation: %s\n", ++ Orientation & 1 ? "Landscape" : "Portrait"); + + /* + * Download any missing fonts... diff --git a/pkgs/core/cups/patches/cups-uri-compat.patch b/pkgs/core/cups/patches/cups-uri-compat.patch new file mode 100644 index 0000000..dd55b66 --- /dev/null +++ b/pkgs/core/cups/patches/cups-uri-compat.patch @@ -0,0 +1,51 @@ +diff -up cups-1.4rc1/backend/usb-unix.c.uri-compat cups-1.4rc1/backend/usb-unix.c +--- cups-1.4rc1/backend/usb-unix.c.uri-compat 2009-07-15 10:48:46.992133677 +0100 ++++ cups-1.4rc1/backend/usb-unix.c 2009-07-15 10:49:05.305008114 +0100 +@@ -63,11 +63,34 @@ print_device(const char *uri, /* I - De + int device_fd; /* USB device */ + size_t tbytes; /* Total number of bytes written */ + struct termios opts; /* Parallel port options */ ++ char *fixed_uri = strdup (uri); ++ char *p; + + + (void)argc; + (void)argv; + ++ p = strchr (fixed_uri, ':'); ++ if (p++ != NULL) ++ { ++ char *e; ++ p += strspn (p, "/"); ++ e = strchr (p, '/'); ++ if (e > p) ++ { ++ size_t mfrlen = e - p; ++ e++; ++ if (!strncasecmp (e, p, mfrlen)) ++ { ++ char *x = e + mfrlen; ++ if (!strncmp (x, "%20", 3)) ++ /* Take mfr name out of mdl name for compatibility with ++ * Fedora 11 before bug #507244 was fixed. */ ++ strcpy (e, x + 3); puts(fixed_uri); ++ } ++ } ++ } ++ + /* + * Open the USB port device... + */ +@@ -107,10 +130,10 @@ print_device(const char *uri, /* I - De + strncasecmp(hostname, "Minolta", 7); + #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */ + +- if (use_bc && !strncmp(uri, "usb:/dev/", 9)) ++ if (use_bc && !strncmp(fixed_uri, "usb:/dev/", 9)) + use_bc = 0; + +- if ((device_fd = open_device(uri, &use_bc)) == -1) ++ if ((device_fd = open_device(fixed_uri, &use_bc)) == -1) + { + if (getenv("CLASS") != NULL) + { diff --git a/pkgs/core/cups/patches/cups-usb-paperout.patch b/pkgs/core/cups/patches/cups-usb-paperout.patch new file mode 100644 index 0000000..fb69145 --- /dev/null +++ b/pkgs/core/cups/patches/cups-usb-paperout.patch @@ -0,0 +1,52 @@ +diff -up cups-1.4b1/backend/usb-unix.c.usb-paperout cups-1.4b1/backend/usb-unix.c +--- cups-1.4b1/backend/usb-unix.c.usb-paperout 2008-11-12 09:30:03.000000000 +0000 ++++ cups-1.4b1/backend/usb-unix.c 2008-11-12 09:30:03.000000000 +0000 +@@ -30,6 +30,11 @@ + + #include <sys/select.h> + ++#ifdef __linux ++#include <sys/ioctl.h> ++#include <linux/lp.h> ++#endif /* __linux */ ++ + + /* + * Local functions... +@@ -324,7 +329,19 @@ open_device(const char *uri, /* I - Dev + if (!strncmp(uri, "usb:/dev/", 9)) + #ifdef __linux + { +- return (open(uri + 4, O_RDWR | O_EXCL)); ++ fd = open(uri + 4, O_RDWR | O_EXCL); ++ ++ if (fd != -1) ++ { ++ /* ++ * Tell the driver to return from write() with errno==ENOSPACE ++ * on paper-out. ++ */ ++ unsigned int t = 1; ++ ioctl (fd, LPABORT, &t); ++ } ++ ++ return fd; + } + else if (!strncmp(uri, "usb://", 6)) + { +@@ -390,7 +407,14 @@ open_device(const char *uri, /* I - Dev + if (!strcmp(uri, device_uri)) + { + /* +- * Yes, return this file descriptor... ++ * Yes, tell the driver to return from write() with ++ * errno==ENOSPACE on paper-out. ++ */ ++ unsigned int t = 1; ++ ioctl (fd, LPABORT, &t); ++ ++ /* ++ * Return this file descriptor... + */ + + fprintf(stderr, "DEBUG: Printer using device file "%s"...\n", diff --git a/pkgs/core/cups/patches/cups-x-lspp.patch b/pkgs/core/cups/patches/cups-x-lspp.patch new file mode 100644 index 0000000..380b55d --- /dev/null +++ b/pkgs/core/cups/patches/cups-x-lspp.patch @@ -0,0 +1,2839 @@ +diff -up cups-1.4.5/config.h.in.lspp cups-1.4.5/config.h.in +--- cups-1.4.5/config.h.in.lspp 2010-12-24 13:21:31.134859403 +0000 ++++ cups-1.4.5/config.h.in 2010-12-24 13:21:31.173858387 +0000 +@@ -672,6 +672,12 @@ + #undef HAVE_SYS_STATVFS_H + #undef HAVE_SYS_VFS_H + ++/* ++ * Are we trying to meet LSPP requirements? ++ */ ++ ++#undef WITH_LSPP ++ + + #endif /* !_CUPS_CONFIG_H_ */ + +diff -up cups-1.4.5/config-scripts/cups-lspp.m4.lspp cups-1.4.5/config-scripts/cups-lspp.m4 +--- cups-1.4.5/config-scripts/cups-lspp.m4.lspp 2010-12-24 13:21:31.174858361 +0000 ++++ cups-1.4.5/config-scripts/cups-lspp.m4 2010-12-24 13:21:31.174858361 +0000 +@@ -0,0 +1,36 @@ ++dnl ++dnl LSPP code for the Common UNIX Printing System (CUPS). ++dnl ++dnl Copyright 2005-2006 by Hewlett-Packard Development Company, L.P. ++dnl ++dnl This program is free software; you can redistribute it and/or modify ++dnl it under the terms of the GNU General Public License as published by ++dnl the Free Software Foundation; version 2. ++dnl ++dnl This program is distributed in the hope that it will be useful, but ++dnl WITHOUT ANY WARRANTY; without even the implied warranty of ++dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++dnl General Public License for more details. ++dnl ++dnl You should have received a copy of the GNU General Public License ++dnl along with this program; if not, write to the Free Software Foundation, ++dnl Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301 USA ++dnl ++ ++dnl Are we trying to meet LSPP requirements ++AC_ARG_ENABLE(lspp, [ --enable-lspp turn on auditing and label support, default=no]) ++ ++if test x"$enable_lspp" != xno; then ++ case "$uname" in ++ Linux) ++ AC_CHECK_LIB(audit,audit_log_user_message, [LIBAUDIT="-laudit" AC_SUBST(LIBAUDIT)]) ++ AC_CHECK_HEADER(libaudit.h) ++ AC_CHECK_LIB(selinux,getpeercon, [LIBSELINUX="-lselinux" AC_SUBST(LIBSELINUX)]) ++ AC_CHECK_HEADER(selinux/selinux.h) ++ AC_DEFINE(WITH_LSPP) ++ ;; ++ *) ++ # All others ++ ;; ++ esac ++fi +diff -up cups-1.4.5/configure.in.lspp cups-1.4.5/configure.in +--- cups-1.4.5/configure.in.lspp 2010-06-22 22:42:44.000000000 +0100 ++++ cups-1.4.5/configure.in 2010-12-24 13:21:31.174858362 +0000 +@@ -42,6 +42,8 @@ sinclude(config-scripts/cups-pap.m4) + sinclude(config-scripts/cups-pdf.m4) + sinclude(config-scripts/cups-scripting.m4) + ++sinclude(config-scripts/cups-lspp.m4) ++ + INSTALL_LANGUAGES="" + UNINSTALL_LANGUAGES="" + LANGFILES="" +diff -up cups-1.4.5/cups/cups.h.lspp cups-1.4.5/cups/cups.h +--- cups-1.4.5/cups/cups.h.lspp 2010-06-22 04:18:27.000000000 +0100 ++++ cups-1.4.5/cups/cups.h 2010-12-24 13:21:31.176858307 +0000 +@@ -15,6 +15,9 @@ + * This file is subject to the Apple OS-Developed Software exception. + */ + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + #ifndef _CUPS_CUPS_H_ + # define _CUPS_CUPS_H_ + +@@ -86,6 +89,12 @@ extern "C" { + # define CUPS_WHICHJOBS_COMPLETED 1 + + ++# ifdef WITH_LSPP ++# define MLS_CONFIG "mls" ++# define TE_CONFIG "te" ++# define SELINUX_CONFIG "SELinux" ++# define UNKNOWN_SL "UNKNOWN SL" ++# endif /* WITH_LSPP */ + /* + * Types and structures... + */ +diff -up cups-1.4.5/data/Makefile.lspp cups-1.4.5/data/Makefile +--- cups-1.4.5/data/Makefile.lspp 2008-11-12 19:30:57.000000000 +0000 ++++ cups-1.4.5/data/Makefile 2010-12-24 13:21:31.177858282 +0000 +@@ -25,7 +25,10 @@ BANNERS = \ + secret \ + standard \ + topsecret \ +- unclassified ++ unclassified \ ++ selinux \ ++ mls \ ++ te + + CHARMAPS = \ + euc-cn.txt \ +diff -up cups-1.4.5/data/mls.lspp cups-1.4.5/data/mls +--- cups-1.4.5/data/mls.lspp 2010-12-24 13:21:31.177858282 +0000 ++++ cups-1.4.5/data/mls 2010-12-24 13:21:31.178858258 +0000 +@@ -0,0 +1,261 @@ ++%!PS-Adobe-3.0 ++%%BoundingBox: 0 0 612 792 ++%%Pages: 1 ++%%LanguageLevel: 1 ++%%DocumentData: Clean7Bit ++%%DocumentSuppliedResources: procset bannerprint/1.0 ++%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman ++%%Creator: Michael Sweet, Easy Software Products ++%%CreationDate: May 10, 2000 ++%%Title: Test Page ++%%EndComments ++%%BeginProlog ++%%BeginResource procset bannerprint 1.1 0 ++% ++% PostScript banner page for the Common UNIX Printing System ("CUPS"). ++% ++% Copyright 1993-2005 by Easy Software Products ++% ++% These coded instructions, statements, and computer programs are the ++% property of Easy Software Products and are protected by Federal ++% copyright law. Distribution and use rights are outlined in the file ++% "LICENSE.txt" which should have been included with this file. If this ++% file is missing or damaged please contact Easy Software Products ++% at: ++% ++% Attn: CUPS Licensing Information ++% Easy Software Products ++% 44141 Airport View Drive, Suite 204 ++% Hollywood, Maryland 20636 USA ++% ++% Voice: (301) 373-9600 ++% EMail: cups-info@cups.org ++% WWW: http://www.cups.org ++% ++/CENTER { % Draw centered text ++ % (name) CENTER - ++ dup stringwidth pop % Get the width of the string ++ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance ++ show % Show the string ++} bind def ++/RIGHT { % Draw right-justified text ++ % (name) RIGHT - ++ dup stringwidth pop % Get the width of the string ++ neg 0 rmoveto % Shift left the entire distance ++ show % Show the string ++} bind def ++/NUMBER { % Draw a number ++ % power n NUMBER - ++ 1 index 1 eq { % power == 1? ++ round cvi exch pop % Convert "n" to integer ++ } { ++ 1 index mul round exch div % Truncate extra decimal places ++ } ifelse ++ 100 string cvs show % Convert to a string and show it... ++} bind def ++/CUPSLOGO { % Draw the CUPS logo ++ % height CUPSLOGO ++ % Start with a big C... ++ /Helvetica findfont 1 index scalefont setfont ++ 0 setgray ++ 0 0 moveto ++ (C) show ++ ++ % Then "UNIX Printing System" much smaller... ++ /Helvetica-Bold findfont 1 index 9 div scalefont setfont ++ 0.25 mul ++ dup dup 2.0 mul moveto ++ (UNIX) show ++ dup dup 1.6 mul moveto ++ (Printing) show ++ dup 1.2 mul moveto ++ (System) show ++} bind def ++/ESPLOGO { % Draw the ESP logo ++ % height ESPLOGO ++ % Compute the size of the logo... ++ 0 0 ++ 2 index 1.5 mul 3 index ++ ++ % Do the "metallic" fill from 10% black to 40% black... ++ 1 -0.001 0 { ++ dup % loopval ++ -0.15 mul % loopval * -0.15 ++ 0.9 add % 0.9 - loopval * 0.15 ++ setgray % set gray shade ++ ++ 0 % x ++ 1 index neg % loopval ++ 1 add % 1 - loopval ++ 3 index % height ++ mul % height * (1 - loopval) ++ moveto % starting point ++ ++ dup % loopval ++ 3 index % width ++ mul % loopval * width ++ 2 index % height ++ lineto % Next point ++ ++ 0 % x ++ 2 index % height ++ lineto % Next point ++ ++ closepath ++ fill ++ ++ dup % loopval ++ 0.15 mul % loopval * 0.15 ++ 0.6 add % 0.6 + loopval * 0.15 ++ setgray ++ ++ dup % loopval ++ neg 1 add % 1 - loopval ++ 3 index % width ++ mul % (1 - loopval) * width ++ 0 % y ++ moveto % Starting point ++ ++ 2 index % width ++ exch % loopval ++ 2 index % height ++ mul % loopval * height ++ lineto % Next point ++ ++ 1 index % width ++ 0 % y ++ lineto % Next point ++ ++ closepath ++ fill ++ } for ++ ++ 0 setgray rectstroke ++ ++ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont ++ dup 40 div ++ ++ dup 4 mul 1 index 25 mul moveto (E) show ++ dup 10 mul 1 index 15 mul moveto (S) show ++ dup 16 mul 1 index 5 mul moveto (P) show ++ ++ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont ++ dup 14 mul 1 index 29 mul moveto (asy) show ++ dup 20 mul 1 index 19 mul moveto (oftware) show ++ dup 26 mul 1 index 9 mul moveto (roducts) show ++ ++ pop ++} bind def ++%%EndResource ++%%EndProlog ++%%Page: 1 1 ++gsave ++ ++ % Determine the imageable area and device resolution... ++ initclip newpath clippath pathbbox % Get bounding rectangle ++ 72 div /pageTop exch def % Get top margin in inches ++ 72 div /pageRight exch def % Get right margin in inches ++ 72 div /pageBottom exch def % Get bottom margin in inches ++ 72 div /pageLeft exch def % Get left margin in inches ++ ++ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft ++ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom ++ ++ /boxWidth % width of text box ++ pageWidth pageHeight lt ++ { pageWidth 54 mul } ++ { pageHeight 42 mul } ++ ifelse def ++ ++ newpath % Clear bounding path ++ ++ % Create fonts... ++ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold ++ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) ++ ++ /mediumFont /Helvetica findfont % mediumFont = Helvetica ++ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) ++ ++ % Offset page to account for lower-left margin... ++ pageLeft 72 mul ++ pageBottom 72 mul ++ translate ++ ++ % Job information box... ++ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 ++ boxWidth 0.5 mul sub % x-= 1/2 box width ++ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 ++ boxWidth % w = box width ++ pageHeight 14 mul % h = pageHeight * 1/2 * 72 ++ 0.5 setgray rectfill % Draw a shadow ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ boxWidth 0.5 mul sub % x-= 1/2 box width ++ pageHeight 30 mul % y = pageHeight * 1/4 * 72 ++ boxWidth % w = box width ++ pageHeight 14 mul % h = pageHeight * 1/2 * 72 ++ ++ 4 copy 1 setgray rectfill % Clear the box to white ++ 0 setgray rectstroke % Draw a black box around it... ++ ++ % Job information text... ++ mediumFont setfont % Medium sized font ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight 5 mul add % y += 2 lines ++ 2 copy % Copy X & Y ++ moveto ++ (Job ID: ) RIGHT ++ moveto ++ ({printer-name}-{job-id}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight 2 mul add % y += 1 line ++ 2 copy % Copy X & Y ++ moveto ++ (Title: ) RIGHT ++ moveto ++ ({job-name}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight -1 mul add % y -= 1 line ++ 2 copy % Copy X & Y ++ moveto ++ (Requesting User: ) RIGHT ++ moveto ++ ({job-originating-user-name}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight -4 mul add % y -= 2 lines ++ 2 copy % Copy X & Y ++ moveto ++ (Billing Info: ) RIGHT ++ moveto ++ ({?job-billing}) show ++ ++ % Then the CUPS logo.... ++ gsave ++ pageWidth 4 mul ++ pageWidth 6 mul ++ translate ++ pageWidth 9 mul CUPSLOGO ++ grestore ++ ++ % And the ESP logo.... ++ gsave ++ pageWidth 59 mul ++ pageWidth 6 mul ++ translate ++ pageWidth 6 mul ESPLOGO ++ grestore ++% Show the page... ++grestore ++showpage ++% ++% End of "$Id: mls_template,v 1.1 2005/06/27 18:44:46 colmo Exp $". ++% ++%%EOF +diff -up cups-1.4.5/data/selinux.lspp cups-1.4.5/data/selinux +--- cups-1.4.5/data/selinux.lspp 2010-12-24 13:21:31.178858258 +0000 ++++ cups-1.4.5/data/selinux 2010-12-24 13:21:31.179858233 +0000 +@@ -0,0 +1,261 @@ ++%!PS-Adobe-3.0 ++%%BoundingBox: 0 0 612 792 ++%%Pages: 1 ++%%LanguageLevel: 1 ++%%DocumentData: Clean7Bit ++%%DocumentSuppliedResources: procset bannerprint/1.0 ++%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman ++%%Creator: Michael Sweet, Easy Software Products ++%%CreationDate: May 10, 2000 ++%%Title: Test Page ++%%EndComments ++%%BeginProlog ++%%BeginResource procset bannerprint 1.1 0 ++% ++% PostScript banner page for the Common UNIX Printing System ("CUPS"). ++% ++% Copyright 1993-2005 by Easy Software Products ++% ++% These coded instructions, statements, and computer programs are the ++% property of Easy Software Products and are protected by Federal ++% copyright law. Distribution and use rights are outlined in the file ++% "LICENSE.txt" which should have been included with this file. If this ++% file is missing or damaged please contact Easy Software Products ++% at: ++% ++% Attn: CUPS Licensing Information ++% Easy Software Products ++% 44141 Airport View Drive, Suite 204 ++% Hollywood, Maryland 20636 USA ++% ++% Voice: (301) 373-9600 ++% EMail: cups-info@cups.org ++% WWW: http://www.cups.org ++% ++/CENTER { % Draw centered text ++ % (name) CENTER - ++ dup stringwidth pop % Get the width of the string ++ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance ++ show % Show the string ++} bind def ++/RIGHT { % Draw right-justified text ++ % (name) RIGHT - ++ dup stringwidth pop % Get the width of the string ++ neg 0 rmoveto % Shift left the entire distance ++ show % Show the string ++} bind def ++/NUMBER { % Draw a number ++ % power n NUMBER - ++ 1 index 1 eq { % power == 1? ++ round cvi exch pop % Convert "n" to integer ++ } { ++ 1 index mul round exch div % Truncate extra decimal places ++ } ifelse ++ 100 string cvs show % Convert to a string and show it... ++} bind def ++/CUPSLOGO { % Draw the CUPS logo ++ % height CUPSLOGO ++ % Start with a big C... ++ /Helvetica findfont 1 index scalefont setfont ++ 0 setgray ++ 0 0 moveto ++ (C) show ++ ++ % Then "UNIX Printing System" much smaller... ++ /Helvetica-Bold findfont 1 index 9 div scalefont setfont ++ 0.25 mul ++ dup dup 2.0 mul moveto ++ (UNIX) show ++ dup dup 1.6 mul moveto ++ (Printing) show ++ dup 1.2 mul moveto ++ (System) show ++} bind def ++/ESPLOGO { % Draw the ESP logo ++ % height ESPLOGO ++ % Compute the size of the logo... ++ 0 0 ++ 2 index 1.5 mul 3 index ++ ++ % Do the "metallic" fill from 10% black to 40% black... ++ 1 -0.001 0 { ++ dup % loopval ++ -0.15 mul % loopval * -0.15 ++ 0.9 add % 0.9 - loopval * 0.15 ++ setgray % set gray shade ++ ++ 0 % x ++ 1 index neg % loopval ++ 1 add % 1 - loopval ++ 3 index % height ++ mul % height * (1 - loopval) ++ moveto % starting point ++ ++ dup % loopval ++ 3 index % width ++ mul % loopval * width ++ 2 index % height ++ lineto % Next point ++ ++ 0 % x ++ 2 index % height ++ lineto % Next point ++ ++ closepath ++ fill ++ ++ dup % loopval ++ 0.15 mul % loopval * 0.15 ++ 0.6 add % 0.6 + loopval * 0.15 ++ setgray ++ ++ dup % loopval ++ neg 1 add % 1 - loopval ++ 3 index % width ++ mul % (1 - loopval) * width ++ 0 % y ++ moveto % Starting point ++ ++ 2 index % width ++ exch % loopval ++ 2 index % height ++ mul % loopval * height ++ lineto % Next point ++ ++ 1 index % width ++ 0 % y ++ lineto % Next point ++ ++ closepath ++ fill ++ } for ++ ++ 0 setgray rectstroke ++ ++ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont ++ dup 40 div ++ ++ dup 4 mul 1 index 25 mul moveto (E) show ++ dup 10 mul 1 index 15 mul moveto (S) show ++ dup 16 mul 1 index 5 mul moveto (P) show ++ ++ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont ++ dup 14 mul 1 index 29 mul moveto (asy) show ++ dup 20 mul 1 index 19 mul moveto (oftware) show ++ dup 26 mul 1 index 9 mul moveto (roducts) show ++ ++ pop ++} bind def ++%%EndResource ++%%EndProlog ++%%Page: 1 1 ++gsave ++ ++ % Determine the imageable area and device resolution... ++ initclip newpath clippath pathbbox % Get bounding rectangle ++ 72 div /pageTop exch def % Get top margin in inches ++ 72 div /pageRight exch def % Get right margin in inches ++ 72 div /pageBottom exch def % Get bottom margin in inches ++ 72 div /pageLeft exch def % Get left margin in inches ++ ++ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft ++ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom ++ ++ /boxWidth % width of text box ++ pageWidth pageHeight lt ++ { pageWidth 54 mul } ++ { pageHeight 42 mul } ++ ifelse def ++ ++ newpath % Clear bounding path ++ ++ % Create fonts... ++ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold ++ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) ++ ++ /mediumFont /Helvetica findfont % mediumFont = Helvetica ++ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) ++ ++ % Offset page to account for lower-left margin... ++ pageLeft 72 mul ++ pageBottom 72 mul ++ translate ++ ++ % Job information box... ++ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 ++ boxWidth 0.5 mul sub % x-= 1/2 box width ++ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 ++ boxWidth % w = box width ++ pageHeight 14 mul % h = pageHeight * 1/2 * 72 ++ 0.5 setgray rectfill % Draw a shadow ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ boxWidth 0.5 mul sub % x-= 1/2 box width ++ pageHeight 30 mul % y = pageHeight * 1/4 * 72 ++ boxWidth % w = box width ++ pageHeight 14 mul % h = pageHeight * 1/2 * 72 ++ ++ 4 copy 1 setgray rectfill % Clear the box to white ++ 0 setgray rectstroke % Draw a black box around it... ++ ++ % Job information text... ++ mediumFont setfont % Medium sized font ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight 5 mul add % y += 2 lines ++ 2 copy % Copy X & Y ++ moveto ++ (Job ID: ) RIGHT ++ moveto ++ ({printer-name}-{job-id}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight 2 mul add % y += 1 line ++ 2 copy % Copy X & Y ++ moveto ++ (Title: ) RIGHT ++ moveto ++ ({job-name}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight -1 mul add % y -= 1 line ++ 2 copy % Copy X & Y ++ moveto ++ (Requesting User: ) RIGHT ++ moveto ++ ({job-originating-user-name}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight -4 mul add % y -= 2 lines ++ 2 copy % Copy X & Y ++ moveto ++ (Billing Info: ) RIGHT ++ moveto ++ ({?job-billing}) show ++ ++ % Then the CUPS logo.... ++ gsave ++ pageWidth 4 mul ++ pageWidth 6 mul ++ translate ++ pageWidth 9 mul CUPSLOGO ++ grestore ++ ++ % And the ESP logo.... ++ gsave ++ pageWidth 59 mul ++ pageWidth 6 mul ++ translate ++ pageWidth 6 mul ESPLOGO ++ grestore ++% Show the page... ++grestore ++showpage ++% ++% End of "$Id: mls_template,v 1.1 2005/06/27 18:44:46 colmo Exp $". ++% ++%%EOF +diff -up cups-1.4.5/data/te.lspp cups-1.4.5/data/te +--- cups-1.4.5/data/te.lspp 2010-12-24 13:21:31.179858233 +0000 ++++ cups-1.4.5/data/te 2010-12-24 13:21:31.180858207 +0000 +@@ -0,0 +1,261 @@ ++%!PS-Adobe-3.0 ++%%BoundingBox: 0 0 612 792 ++%%Pages: 1 ++%%LanguageLevel: 1 ++%%DocumentData: Clean7Bit ++%%DocumentSuppliedResources: procset bannerprint/1.0 ++%%DocumentNeededResources: font Helvetica Helvetica-Bold Times-Roman ++%%Creator: Michael Sweet, Easy Software Products ++%%CreationDate: May 10, 2000 ++%%Title: Test Page ++%%EndComments ++%%BeginProlog ++%%BeginResource procset bannerprint 1.1 0 ++% ++% PostScript banner page for the Common UNIX Printing System ("CUPS"). ++% ++% Copyright 1993-2005 by Easy Software Products ++% ++% These coded instructions, statements, and computer programs are the ++% property of Easy Software Products and are protected by Federal ++% copyright law. Distribution and use rights are outlined in the file ++% "LICENSE.txt" which should have been included with this file. If this ++% file is missing or damaged please contact Easy Software Products ++% at: ++% ++% Attn: CUPS Licensing Information ++% Easy Software Products ++% 44141 Airport View Drive, Suite 204 ++% Hollywood, Maryland 20636 USA ++% ++% Voice: (301) 373-9600 ++% EMail: cups-info@cups.org ++% WWW: http://www.cups.org ++% ++/CENTER { % Draw centered text ++ % (name) CENTER - ++ dup stringwidth pop % Get the width of the string ++ 0.5 mul neg 0 rmoveto % Shift left 1/2 of the distance ++ show % Show the string ++} bind def ++/RIGHT { % Draw right-justified text ++ % (name) RIGHT - ++ dup stringwidth pop % Get the width of the string ++ neg 0 rmoveto % Shift left the entire distance ++ show % Show the string ++} bind def ++/NUMBER { % Draw a number ++ % power n NUMBER - ++ 1 index 1 eq { % power == 1? ++ round cvi exch pop % Convert "n" to integer ++ } { ++ 1 index mul round exch div % Truncate extra decimal places ++ } ifelse ++ 100 string cvs show % Convert to a string and show it... ++} bind def ++/CUPSLOGO { % Draw the CUPS logo ++ % height CUPSLOGO ++ % Start with a big C... ++ /Helvetica findfont 1 index scalefont setfont ++ 0 setgray ++ 0 0 moveto ++ (C) show ++ ++ % Then "UNIX Printing System" much smaller... ++ /Helvetica-Bold findfont 1 index 9 div scalefont setfont ++ 0.25 mul ++ dup dup 2.0 mul moveto ++ (UNIX) show ++ dup dup 1.6 mul moveto ++ (Printing) show ++ dup 1.2 mul moveto ++ (System) show ++} bind def ++/ESPLOGO { % Draw the ESP logo ++ % height ESPLOGO ++ % Compute the size of the logo... ++ 0 0 ++ 2 index 1.5 mul 3 index ++ ++ % Do the "metallic" fill from 10% black to 40% black... ++ 1 -0.001 0 { ++ dup % loopval ++ -0.15 mul % loopval * -0.15 ++ 0.9 add % 0.9 - loopval * 0.15 ++ setgray % set gray shade ++ ++ 0 % x ++ 1 index neg % loopval ++ 1 add % 1 - loopval ++ 3 index % height ++ mul % height * (1 - loopval) ++ moveto % starting point ++ ++ dup % loopval ++ 3 index % width ++ mul % loopval * width ++ 2 index % height ++ lineto % Next point ++ ++ 0 % x ++ 2 index % height ++ lineto % Next point ++ ++ closepath ++ fill ++ ++ dup % loopval ++ 0.15 mul % loopval * 0.15 ++ 0.6 add % 0.6 + loopval * 0.15 ++ setgray ++ ++ dup % loopval ++ neg 1 add % 1 - loopval ++ 3 index % width ++ mul % (1 - loopval) * width ++ 0 % y ++ moveto % Starting point ++ ++ 2 index % width ++ exch % loopval ++ 2 index % height ++ mul % loopval * height ++ lineto % Next point ++ ++ 1 index % width ++ 0 % y ++ lineto % Next point ++ ++ closepath ++ fill ++ } for ++ ++ 0 setgray rectstroke ++ ++ /Helvetica-BoldOblique findfont 1 index 3 div scalefont setfont ++ dup 40 div ++ ++ dup 4 mul 1 index 25 mul moveto (E) show ++ dup 10 mul 1 index 15 mul moveto (S) show ++ dup 16 mul 1 index 5 mul moveto (P) show ++ ++ /Helvetica-BoldOblique findfont 2 index 5 div scalefont setfont ++ dup 14 mul 1 index 29 mul moveto (asy) show ++ dup 20 mul 1 index 19 mul moveto (oftware) show ++ dup 26 mul 1 index 9 mul moveto (roducts) show ++ ++ pop ++} bind def ++%%EndResource ++%%EndProlog ++%%Page: 1 1 ++gsave ++ ++ % Determine the imageable area and device resolution... ++ initclip newpath clippath pathbbox % Get bounding rectangle ++ 72 div /pageTop exch def % Get top margin in inches ++ 72 div /pageRight exch def % Get right margin in inches ++ 72 div /pageBottom exch def % Get bottom margin in inches ++ 72 div /pageLeft exch def % Get left margin in inches ++ ++ /pageWidth pageRight pageLeft sub def % pageWidth = pageRight - pageLeft ++ /pageHeight pageTop pageBottom sub def% pageHeight = pageTop - pageBottom ++ ++ /boxWidth % width of text box ++ pageWidth pageHeight lt ++ { pageWidth 54 mul } ++ { pageHeight 42 mul } ++ ifelse def ++ ++ newpath % Clear bounding path ++ ++ % Create fonts... ++ /bigFont /Helvetica-Bold findfont % bigFont = Helvetica-Bold ++ pageHeight 3 mul scalefont def % size = pageHeight * 3 (nominally 33) ++ ++ /mediumFont /Helvetica findfont % mediumFont = Helvetica ++ pageHeight 1.5 mul scalefont def % size = pageHeight * 1.5 (nominally 16.5) ++ ++ % Offset page to account for lower-left margin... ++ pageLeft 72 mul ++ pageBottom 72 mul ++ translate ++ ++ % Job information box... ++ pageWidth 36 mul 9 add % x = pageWidth * 1/2 * 72 + 9 ++ boxWidth 0.5 mul sub % x-= 1/2 box width ++ pageHeight 30 mul 9 sub % y = pageHeight * 1/2 * 72 - 9 ++ boxWidth % w = box width ++ pageHeight 14 mul % h = pageHeight * 1/2 * 72 ++ 0.5 setgray rectfill % Draw a shadow ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ boxWidth 0.5 mul sub % x-= 1/2 box width ++ pageHeight 30 mul % y = pageHeight * 1/4 * 72 ++ boxWidth % w = box width ++ pageHeight 14 mul % h = pageHeight * 1/2 * 72 ++ ++ 4 copy 1 setgray rectfill % Clear the box to white ++ 0 setgray rectstroke % Draw a black box around it... ++ ++ % Job information text... ++ mediumFont setfont % Medium sized font ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight 5 mul add % y += 2 lines ++ 2 copy % Copy X & Y ++ moveto ++ (Job ID: ) RIGHT ++ moveto ++ ({printer-name}-{job-id}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight 2 mul add % y += 1 line ++ 2 copy % Copy X & Y ++ moveto ++ (Title: ) RIGHT ++ moveto ++ ({job-name}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight -1 mul add % y -= 1 line ++ 2 copy % Copy X & Y ++ moveto ++ (Requesting User: ) RIGHT ++ moveto ++ ({job-originating-user-name}) show ++ ++ pageWidth 36 mul % x = pageWidth * 1/2 * 72 ++ pageHeight 36 mul % y = pageHeight * 1/2 * 72 ++ pageHeight -4 mul add % y -= 2 lines ++ 2 copy % Copy X & Y ++ moveto ++ (Billing Info: ) RIGHT ++ moveto ++ ({?job-billing}) show ++ ++ % Then the CUPS logo.... ++ gsave ++ pageWidth 4 mul ++ pageWidth 6 mul ++ translate ++ pageWidth 9 mul CUPSLOGO ++ grestore ++ ++ % And the ESP logo.... ++ gsave ++ pageWidth 59 mul ++ pageWidth 6 mul ++ translate ++ pageWidth 6 mul ESPLOGO ++ grestore ++% Show the page... ++grestore ++showpage ++% ++% End of "$Id: mls_template,v 1.1 2005/06/27 18:44:46 colmo Exp $". ++% ++%%EOF +diff -up cups-1.4.5/filter/common.c.lspp cups-1.4.5/filter/common.c +--- cups-1.4.5/filter/common.c.lspp 2007-07-11 22:46:42.000000000 +0100 ++++ cups-1.4.5/filter/common.c 2010-12-24 13:21:31.181858180 +0000 +@@ -30,6 +30,12 @@ + * Include necessary headers... + */ + ++#include "config.h" ++#ifdef WITH_LSPP ++#define _GNU_SOURCE ++#include <string.h> ++#endif /* WITH_LSPP */ ++ + #include "common.h" + #include <locale.h> + +@@ -312,6 +318,18 @@ WriteLabelProlog(const char *label, /* I + { + const char *classification; /* CLASSIFICATION environment variable */ + const char *ptr; /* Temporary string pointer */ ++#ifdef WITH_LSPP ++ int i, /* counter */ ++ n, /* counter */ ++ lines, /* number of lines needed */ ++ line_len, /* index into tmp_label */ ++ label_len, /* length of the label in characters */ ++ label_index, /* index into the label */ ++ longest, /* length of the longest line */ ++ longest_line, /* index to the longest line */ ++ max_width; /* maximum width in characters */ ++ char **wrapped_label; /* label with line breaks */ ++#endif /* WITH_LSPP */ + + + /* +@@ -334,6 +352,124 @@ WriteLabelProlog(const char *label, /* I + return; + } + ++#ifdef WITH_LSPP ++ if (strncmp(classification, "LSPP:", 5) == 0 && label == NULL) ++ { ++ /* ++ * Based on the 12pt fixed width font below determine the max_width ++ */ ++ max_width = width / 8; ++ longest_line = 0; ++ longest = 0; ++ classification += 5; // Skip the "LSPP:" ++ label_len = strlen(classification); ++ ++ if (label_len > max_width) ++ { ++ lines = 1 + (int)(label_len / max_width); ++ line_len = (int)(label_len / lines); ++ wrapped_label = malloc(sizeof(wrapped_label) * lines); ++ label_index = i = n = 0; ++ while (classification[label_index]) ++ { ++ if ((label_index + line_len) > label_len) ++ break; ++ switch (classification[label_index + line_len + i]) ++ { ++ case ':': ++ case ',': ++ case '-': ++ i++; ++ wrapped_label[n++] = strndup(&classification[label_index], (line_len + i)); ++ label_index += line_len + i; ++ i = 0; ++ break; ++ default: ++ i++; ++ break; ++ } ++ if ((i + line_len) == max_width) ++ { ++ wrapped_label[n++] = strndup(&(classification[label_index]), (line_len + i)); ++ label_index = label_index + line_len + i; ++ i = 0; ++ } ++ } ++ wrapped_label[n] = strndup(&classification[label_index], label_len - label_index); ++ } ++ else ++ { ++ lines = 1; ++ wrapped_label = malloc(sizeof(wrapped_label)); ++ wrapped_label[0] = (char*)classification; ++ } ++ ++ for (n = 0; n < lines; n++ ) ++ { ++ printf("userdict/ESPp%c(", ('a' + n)); ++ for (ptr = wrapped_label[n], i = 0; *ptr; ptr ++, i++) ++ if (*ptr < 32 || *ptr > 126) ++ printf("\%03o", *ptr); ++ else ++ { ++ if (*ptr == '(' || *ptr == ')' || *ptr == '\') ++ putchar('\'); ++ ++ printf("%c", *ptr); ++ } ++ if (i > longest) ++ { ++ longest = i; ++ longest_line = n; ++ } ++ printf(")put\n"); ++ } ++ ++ /* ++ * For LSPP use a fixed width font so that line wrapping can be calculated ++ */ ++ ++ puts("userdict/ESPlf /Nimbus-Mono findfont 12 scalefont put"); ++ ++ /* ++ * Finally, the procedure to write the labels on the page... ++ */ ++ ++ printf("userdict/ESPwl{\n" ++ " ESPlf setfont\n"); ++ printf(" ESPp%c stringwidth pop dup 12 add exch -0.5 mul %.0f add\n ", ++ 'a' + longest_line, width * 0.5f); ++ for (n = 1; n < lines; n++) ++ printf(" dup"); ++ printf("\n 1 setgray\n"); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", ++ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", ++ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); ++ printf(" 0 setgray\n"); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", ++ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", ++ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); ++ for (n = 0; n < lines; n ++) ++ { ++ printf(" dup %.0f moveto ESPp%c show\n", ++ bottom + 6.0 + ((lines - (n+1)) * 16.0), 'a' + n); ++ printf(" %.0f moveto ESPp%c show\n", top + 2.0 - ((n + 1) * 16.0), 'a' + n); ++ } ++ printf(" pop\n" ++ "}bind put\n"); ++ ++ /* ++ * Do some clean up at the end of the LSPP special case ++ */ ++ free(wrapped_label); ++ ++ } ++ else ++ { ++#endif /* !WITH_LSPP */ ++ + /* + * Set the classification + page label string... + */ +@@ -414,7 +550,10 @@ WriteLabelProlog(const char *label, /* I + printf(" %.0f moveto ESPpl show\n", top - 14.0); + puts("pop"); + puts("}bind put"); ++ } ++#ifdef WITH_LSPP + } ++#endif /* WITH_LSPP */ + + + /* +diff -up cups-1.4.5/filter/pstops.c.lspp cups-1.4.5/filter/pstops.c +--- cups-1.4.5/filter/pstops.c.lspp 2010-12-24 13:21:30.960863932 +0000 ++++ cups-1.4.5/filter/pstops.c 2010-12-24 13:21:31.186858049 +0000 +@@ -3335,6 +3335,18 @@ write_label_prolog(pstops_doc_t *doc, /* + { + const char *classification; /* CLASSIFICATION environment variable */ + const char *ptr; /* Temporary string pointer */ ++#ifdef WITH_LSPP ++ int i, /* counter */ ++ n, /* counter */ ++ lines, /* number of lines needed */ ++ line_len, /* index into tmp_label */ ++ label_len, /* length of the label in characters */ ++ label_index, /* index into the label */ ++ longest, /* length of the longest line */ ++ longest_line, /* index to the longest line */ ++ max_width; /* maximum width in characters */ ++ char **wrapped_label; /* label with line breaks */ ++#endif /* WITH_LSPP */ + + + /* +@@ -3357,6 +3369,124 @@ write_label_prolog(pstops_doc_t *doc, /* + return; + } + ++#ifdef WITH_LSPP ++ if (strncmp(classification, "LSPP:", 5) == 0 && label == NULL) ++ { ++ /* ++ * Based on the 12pt fixed width font below determine the max_width ++ */ ++ max_width = width / 8; ++ longest_line = 0; ++ longest = 0; ++ classification += 5; // Skip the "LSPP:" ++ label_len = strlen(classification); ++ ++ if (label_len > max_width) ++ { ++ lines = 1 + (int)(label_len / max_width); ++ line_len = (int)(label_len / lines); ++ wrapped_label = malloc(sizeof(wrapped_label) * lines); ++ label_index = i = n = 0; ++ while (classification[label_index]) ++ { ++ if ((label_index + line_len) > label_len) ++ break; ++ switch (classification[label_index + line_len + i]) ++ { ++ case ':': ++ case ',': ++ case '-': ++ i++; ++ wrapped_label[n++] = strndup(&classification[label_index], (line_len + i)); ++ label_index += line_len + i; ++ i = 0; ++ break; ++ default: ++ i++; ++ break; ++ } ++ if ((i + line_len) == max_width) ++ { ++ wrapped_label[n++] = strndup(&(classification[label_index]), (line_len + i)); ++ label_index = label_index + line_len + i; ++ i = 0; ++ } ++ } ++ wrapped_label[n] = strndup(&classification[label_index], label_len - label_index); ++ } ++ else ++ { ++ lines = 1; ++ wrapped_label = malloc(sizeof(wrapped_label)); ++ wrapped_label[0] = (char*)classification; ++ } ++ ++ for (n = 0; n < lines; n++ ) ++ { ++ printf("userdict/ESPp%c(", ('a' + n)); ++ for (ptr = wrapped_label[n], i = 0; *ptr; ptr ++, i++) ++ if (*ptr < 32 || *ptr > 126) ++ printf("\%03o", *ptr); ++ else ++ { ++ if (*ptr == '(' || *ptr == ')' || *ptr == '\') ++ putchar('\'); ++ ++ printf("%c", *ptr); ++ } ++ if (i > longest) ++ { ++ longest = i; ++ longest_line = n; ++ } ++ printf(")put\n"); ++ } ++ ++ /* ++ * For LSPP use a fixed width font so that line wrapping can be calculated ++ */ ++ ++ puts("userdict/ESPlf /Nimbus-Mono findfont 12 scalefont put"); ++ ++ /* ++ * Finally, the procedure to write the labels on the page... ++ */ ++ ++ printf("userdict/ESPwl{\n" ++ " ESPlf setfont\n"); ++ printf(" ESPp%c stringwidth pop dup 12 add exch -0.5 mul %.0f add\n ", ++ 'a' + longest_line, width * 0.5f); ++ for (n = 1; n < lines; n++) ++ printf(" dup"); ++ printf("\n 1 setgray\n"); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", ++ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrf\n", ++ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); ++ printf(" 0 setgray\n"); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", ++ (bottom - 2.0), (2 + lines), 6.0 + (16.0 * lines)); ++ printf(" dup 6 sub %.0f %d index %.0f ESPrs\n", ++ (top - 6.0 - (16.0 * lines)), (2 + lines), 4.0 + (16.0 * lines)); ++ for (n = 0; n < lines; n ++) ++ { ++ printf(" dup %.0f moveto ESPp%c show\n", ++ bottom + 6.0 + ((lines - (n+1)) * 16.0), 'a' + n); ++ printf(" %.0f moveto ESPp%c show\n", top + 2.0 - ((n + 1) * 16.0), 'a' + n); ++ } ++ printf(" pop\n" ++ "}bind put\n"); ++ ++ /* ++ * Do some clean up at the end of the LSPP special case ++ */ ++ free(wrapped_label); ++ ++ } ++ else ++ { ++#endif /* !WITH_LSPP */ ++ + /* + * Set the classification + page label string... + */ +@@ -3435,7 +3565,10 @@ write_label_prolog(pstops_doc_t *doc, /* + doc_printf(doc, " %.0f moveto ESPpl show\n", top - 14.0); + doc_puts(doc, "pop\n"); + doc_puts(doc, "}bind put\n"); ++ } ++#ifdef WITH_LSPP + } ++#endif /* WITH_LSPP */ + + + /* +diff -up cups-1.4.5/Makedefs.in.lspp cups-1.4.5/Makedefs.in +--- cups-1.4.5/Makedefs.in.lspp 2010-12-24 13:21:31.073860989 +0000 ++++ cups-1.4.5/Makedefs.in 2010-12-24 13:21:31.187858023 +0000 +@@ -146,7 +146,7 @@ LIBCUPSORDER = @LIBCUPSORDER@ + LIBCUPSIMAGEORDER = @LIBCUPSIMAGEORDER@ + LINKCUPS = @LINKCUPS@ $(SSLLIBS) $(DNSSDLIBS) + LINKCUPSIMAGE = @LINKCUPSIMAGE@ +-LIBS = $(LINKCUPS) $(COMMONLIBS) ++LIBS = $(LINKCUPS) $(COMMONLIBS) @LIBAUDIT@ @LIBSELINUX@ + OPTIM = @OPTIM@ + OPTIONS = + PAMLIBS = @PAMLIBS@ +@@ -258,7 +258,7 @@ DBUSDIR = @DBUSDIR@ + # Rules... + # + +-.SILENT: ++ + .SUFFIXES: .1 .1.gz .1m .1m.gz .3 .3.gz .5 .5.gz .7 .7.gz .8 .8.gz .a .c .cxx .h .man .o .32.o .64.o .gz + + .c.o: +diff -up cups-1.4.5/scheduler/client.c.lspp cups-1.4.5/scheduler/client.c +--- cups-1.4.5/scheduler/client.c.lspp 2010-10-17 05:13:56.000000000 +0100 ++++ cups-1.4.5/scheduler/client.c 2010-12-24 13:21:31.194857839 +0000 +@@ -44,6 +44,7 @@ + * valid_host() - Is the Host: field valid? + * write_file() - Send a file via HTTP. + * write_pipe() - Flag that data is available on the CGI pipe. ++ * client_pid_to_auid() - Get the audit login uid of the client. + */ + + /* +@@ -52,6 +53,7 @@ + + #include "cupsd.h" + ++#define _GNU_SOURCE + #ifdef HAVE_CDSASSL + # include <Security/Security.h> + # include <Security/SecItem.h> +@@ -90,6 +92,12 @@ extern const char *cssmErrorString(int e + # include <tcpd.h> + #endif /* HAVE_TCPD_H */ + ++#ifdef WITH_LSPP ++#include <selinux/selinux.h> ++#include <selinux/context.h> ++#include <fcntl.h> ++#endif /* WITH_LSPP */ ++ + + /* + * Local functions... +@@ -391,6 +399,57 @@ cupsdAcceptClient(cupsd_listener_t *lis) + } + #endif /* HAVE_TCPD_H */ + ++#ifdef WITH_LSPP ++ if (is_lspp_config()) ++ { ++ struct ucred cr; ++ unsigned int cl=sizeof(cr); ++ ++ if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) == 0) ++ { ++ /* ++ * client_pid_to_auid() can be racey ++ * In this case the pid is based on a socket connected to the client ++ */ ++ if ((con->auid = client_pid_to_auid(cr.pid)) == -1) ++ { ++ close(con->http.fd); ++ cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdAcceptClient: " ++ "unable to determine client auid for client pid=%d", cr.pid); ++ free(con); ++ return; ++ } ++ cupsdLogMessage(CUPSD_LOG_INFO, "cupsdAcceptClient: peer's pid=%d, uid=%d, gid=%d, auid=%d", ++ cr.pid, cr.uid, cr.gid, con->auid); ++ } ++ else ++ { ++ close(con->http.fd); ++ cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdAcceptClient: getsockopt() failed"); ++ free(con); ++ return; ++ } ++ ++ /* ++ * get the context of the peer connection ++ */ ++ if (getpeercon(con->http.fd, &con->scon)) ++ { ++ close(con->http.fd); ++ cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdAcceptClient: getpeercon() failed"); ++ free(con); ++ return; ++ } ++ ++ cupsdLogMessage(CUPSD_LOG_INFO, "cupsdAcceptClient: client context=%s", con->scon); ++ } ++ else ++ { ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: skipping getpeercon()"); ++ cupsdSetString(&con->scon, UNKNOWN_SL); ++ } ++#endif /* WITH_LSPP */ ++ + #ifdef AF_INET6 + if (con->http.hostaddr->addr.sa_family == AF_INET6) + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAcceptClient: %d from %s:%d (IPv6)", +@@ -781,6 +840,13 @@ cupsdReadClient(cupsd_client_t *con) /* + mime_type_t *type; /* MIME type of file */ + cupsd_printer_t *p; /* Printer */ + static unsigned request_id = 0; /* Request ID for temp files */ ++#ifdef WITH_LSPP ++ security_context_t spoolcon; /* context of the job file */ ++ context_t clicon; /* contex_t container for con->scon */ ++ context_t tmpcon; /* temp context to swap the level */ ++ char *clirange; /* SELinux sensitivity range */ ++ char *cliclearance; /* SELinux low end clearance */ ++#endif /* WITH_LSPP */ + + + status = HTTP_CONTINUE; +@@ -2135,6 +2201,67 @@ cupsdReadClient(cupsd_client_t *con) /* + fchmod(con->file, 0640); + fchown(con->file, RunUser, Group); + fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); ++#ifdef WITH_LSPP ++ if (strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) ++ { ++ if (getfilecon(con->filename, &spoolcon) == -1) ++ { ++ cupsdSendError(con, HTTP_SERVER_ERROR, CUPSD_AUTH_NONE); ++ return (cupsdCloseClient(con)); ++ } ++ clicon = context_new(con->scon); ++ tmpcon = context_new(spoolcon); ++ freecon(spoolcon); ++ if (!clicon || !tmpcon) ++ { ++ cupsdSendError(con, HTTP_SERVER_ERROR, CUPSD_AUTH_NONE); ++ if (clicon) ++ context_free(clicon); ++ if (tmpcon) ++ context_free(tmpcon); ++ return (cupsdCloseClient(con)); ++ } ++ clirange = context_range_get(clicon); ++ if (clirange) ++ { ++ clirange = strdup(clirange); ++ if ((cliclearance = strtok(clirange, "-")) != NULL) ++ { ++ if (context_range_set(tmpcon, cliclearance) == -1) ++ { ++ cupsdSendError(con, HTTP_SERVER_ERROR, CUPSD_AUTH_NONE); ++ free(clirange); ++ context_free(tmpcon); ++ context_free(clicon); ++ return (cupsdCloseClient(con)); ++ } ++ } ++ else ++ { ++ if (context_range_set(tmpcon, (context_range_get(clicon))) == -1) ++ { ++ cupsdSendError(con, HTTP_SERVER_ERROR, CUPSD_AUTH_NONE); ++ free(clirange); ++ context_free(tmpcon); ++ context_free(clicon); ++ return (cupsdCloseClient(con)); ++ } ++ } ++ free(clirange); ++ } ++ if (setfilecon(con->filename, context_str(tmpcon)) == -1) ++ { ++ cupsdSendError(con, HTTP_SERVER_ERROR, CUPSD_AUTH_NONE); ++ context_free(tmpcon); ++ context_free(clicon); ++ return (cupsdCloseClient(con)); ++ } ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdReadClient: %s set to %s", ++ con->filename, context_str(tmpcon)); ++ context_free(tmpcon); ++ context_free(clicon); ++ } ++#endif /* WITH_LSPP */ + } + + if (con->http.state != HTTP_POST_SEND) +@@ -4641,6 +4768,50 @@ make_certificate(cupsd_client_t *con) /* + #endif /* HAVE_SSL */ + + ++#ifdef WITH_LSPP ++/* ++ * 'client_pid_to_auid()' - Using the client's pid, read /proc and determine the loginuid. ++ */ ++ ++uid_t client_pid_to_auid(pid_t clipid) ++{ ++ uid_t uid; ++ int len, in; ++ char buf[16] = {0}; ++ char fname[32] = {0}; ++ ++ ++ /* ++ * Hopefully this pid is still the one we are interested in. ++ */ ++ snprintf(fname, 32, "/proc/%d/loginuid", clipid); ++ in = open(fname, O_NOFOLLOW|O_RDONLY); ++ ++ if (in < 0) ++ return -1; ++ ++ errno = 0; ++ ++ do { ++ len = read(in, buf, sizeof(buf)); ++ } while (len < 0 && errno == EINTR); ++ ++ close(in); ++ ++ if (len < 0 || len >= sizeof(buf)) ++ return -1; ++ ++ errno = 0; ++ buf[len] = 0; ++ uid = strtol(buf, 0, 10); ++ ++ if (errno != 0) ++ return -1; ++ else ++ return uid; ++} ++#endif /* WITH_LSPP */ ++ + /* + * 'pipe_command()' - Pipe the output of a command to the remote client. + */ +diff -up cups-1.4.5/scheduler/client.h.lspp cups-1.4.5/scheduler/client.h +--- cups-1.4.5/scheduler/client.h.lspp 2009-05-26 23:01:23.000000000 +0100 ++++ cups-1.4.5/scheduler/client.h 2010-12-24 13:21:31.195857813 +0000 +@@ -18,6 +18,13 @@ + #endif /* HAVE_AUTHORIZATION_H */ + + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ ++#ifdef WITH_LSPP ++#include <selinux/selinux.h> ++#endif /* WITH_LSPP */ ++ + /* + * HTTP client structure... + */ +@@ -64,6 +71,10 @@ struct cupsd_client_s + #ifdef HAVE_AUTHORIZATION_H + AuthorizationRef authref; /* Authorization ref */ + #endif /* HAVE_AUTHORIZATION_H */ ++#ifdef WITH_LSPP ++ security_context_t scon; /* Security context of connection */ ++ uid_t auid; /* Audit loginuid of the client */ ++#endif /* WITH_LSPP */ + }; + + #define HTTP(con) &((con)->http) +@@ -133,6 +144,9 @@ extern void cupsdStartListening(void); + extern void cupsdStopListening(void); + extern void cupsdUpdateCGI(void); + extern void cupsdWriteClient(cupsd_client_t *con); ++#ifdef WITH_LSPP ++extern uid_t client_pid_to_auid(pid_t clipid); ++#endif /* WITH_LSPP */ + + + /* +diff -up cups-1.4.5/scheduler/conf.c.lspp cups-1.4.5/scheduler/conf.c +--- cups-1.4.5/scheduler/conf.c.lspp 2010-12-24 13:21:30.897865572 +0000 ++++ cups-1.4.5/scheduler/conf.c 2010-12-24 13:21:31.200857684 +0000 +@@ -29,6 +29,7 @@ + * read_configuration() - Read a configuration file. + * read_location() - Read a <Location path> definition. + * read_policy() - Read a <Policy name> definition. ++ * is_lspp_config() - Is the system configured for LSPP + */ + + /* +@@ -54,6 +55,9 @@ + # define INADDR_NONE 0xffffffff + #endif /* !INADDR_NONE */ + ++#ifdef WITH_LSPP ++# include <libaudit.h> ++#endif /* WITH_LSPP */ + + /* + * Configuration variable structure... +@@ -172,6 +176,10 @@ static const cupsd_var_t variables[] = + # if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS) + { "ServerKey", &ServerKey, CUPSD_VARTYPE_PATHNAME }, + # endif /* HAVE_LIBSSL || HAVE_GNUTLS */ ++#ifdef WITH_LSPP ++ { "AuditLog", &AuditLog, CUPSD_VARTYPE_INTEGER }, ++ { "PerPageLabels", &PerPageLabels, CUPSD_VARTYPE_BOOLEAN }, ++#endif /* WITH_LSPP */ + #endif /* HAVE_SSL */ + { "ServerName", &ServerName, CUPSD_VARTYPE_STRING }, + { "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME }, +@@ -430,6 +438,9 @@ cupsdReadConfiguration(void) + const char *tmpdir; /* TMPDIR environment variable */ + struct stat tmpinfo; /* Temporary directory info */ + cupsd_policy_t *p; /* Policy */ ++#ifdef WITH_LSPP ++ char *audit_message; /* Audit message string */ ++#endif /* WITH_LSPP */ + + + /* +@@ -713,6 +724,25 @@ cupsdReadConfiguration(void) + + RunUser = getuid(); + ++#ifdef WITH_LSPP ++ if (AuditLog != -1) ++ { ++ /* ++ * ClassifyOverride is set during read_configuration, if its ON, report it now ++ */ ++ if (ClassifyOverride) ++ audit_log_user_message(AuditLog, AUDIT_USYS_CONFIG, ++ "[Config] ClassifyOverride=enabled Users can override print banners", ++ ServerName, NULL, NULL, 1); ++ /* ++ * PerPageLabel is set during read_configuration, if its OFF, report it now ++ */ ++ if (!PerPageLabels) ++ audit_log_user_message(AuditLog, AUDIT_USYS_CONFIG, ++ "[Config] PerPageLabels=disabled", ServerName, NULL, NULL, 1); ++ } ++#endif /* WITH_LSPP */ ++ + cupsdLogMessage(CUPSD_LOG_INFO, "Remote access is %s.", + RemotePort ? "enabled" : "disabled"); + +@@ -1081,11 +1111,23 @@ cupsdReadConfiguration(void) + * Update classification setting as needed... + */ + +- if (Classification && !strcasecmp(Classification, "none")) ++ if (Classification && strcasecmp(Classification, "none") == 0) + cupsdClearString(&Classification); + + if (Classification) ++ { + cupsdLogMessage(CUPSD_LOG_INFO, "Security set to "%s"", Classification); ++#ifdef WITH_LSPP ++ if (AuditLog != -1) ++ { ++ audit_message = NULL; ++ cupsdSetStringf(&audit_message, "[Config] Classification=%s", Classification); ++ audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message, ++ ServerName, NULL, NULL, 1); ++ cupsdClearString(&audit_message); ++ } ++#endif /* WITH_LSPP */ ++ } + + /* + * Check the MaxClients setting, and then allocate memory for it... +@@ -3657,6 +3699,18 @@ read_location(cups_file_t *fp, /* I - C + return ((FatalErrors & CUPSD_FATAL_CONFIG) ? 0 : linenum); + } + ++#ifdef WITH_LSPP ++int is_lspp_config() ++{ ++ if (Classification != NULL) ++ return ((strcasecmp(Classification, MLS_CONFIG) == 0) ++ || (strcasecmp(Classification, TE_CONFIG) == 0) ++ || (strcasecmp(Classification, SELINUX_CONFIG) == 0)); ++ else ++ return 0; ++} ++#endif /* WITH_LSPP */ ++ + + /* + * 'read_policy()' - Read a <Policy name> definition. +diff -up cups-1.4.5/scheduler/conf.h.lspp cups-1.4.5/scheduler/conf.h +--- cups-1.4.5/scheduler/conf.h.lspp 2010-12-24 13:21:30.897865572 +0000 ++++ cups-1.4.5/scheduler/conf.h 2010-12-24 13:21:31.202857632 +0000 +@@ -250,6 +250,12 @@ VAR char *ServerKey VALUE(NULL); + VAR int SSLOptions VALUE(CUPSD_SSL_NONE); + /* SSL/TLS options */ + #endif /* HAVE_SSL */ ++#ifdef WITH_LSPP ++VAR int AuditLog VALUE(-1), ++ /* File descriptor for audit */ ++ PerPageLabels VALUE(TRUE); ++ /* Put the label on each page */ ++#endif /* WITH_LSPP */ + + #ifdef HAVE_LAUNCHD + VAR int LaunchdTimeout VALUE(DEFAULT_KEEPALIVE); +@@ -266,6 +272,9 @@ VAR char *SystemGroupAuthKey VALUE(NULL + /* System group auth key */ + #endif /* HAVE_AUTHORIZATION_H */ + ++#ifdef WITH_LSPP ++extern int is_lspp_config(void); ++#endif /* WITH_LSPP */ + + /* + * Prototypes... +diff -up cups-1.4.5/scheduler/ipp.c.lspp cups-1.4.5/scheduler/ipp.c +--- cups-1.4.5/scheduler/ipp.c.lspp 2010-12-24 13:21:31.114859924 +0000 ++++ cups-1.4.5/scheduler/ipp.c 2010-12-24 13:21:31.217857242 +0000 +@@ -41,6 +41,7 @@ + * cancel_all_jobs() - Cancel all print jobs. + * cancel_job() - Cancel a print job. + * cancel_subscription() - Cancel a subscription. ++ * check_context() - Check the SELinux context for a user and job + * check_quotas() - Check quotas for a printer and user. + * check_rss_recipient() - Check that we do not have a duplicate RSS + * feed URI. +@@ -102,6 +103,9 @@ + * validate_user() - Validate the user for the request. + */ + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + /* + * Include necessary headers... + */ +@@ -124,6 +128,14 @@ extern int mbr_check_membership_by_id(uu + # endif /* HAVE_MEMBERSHIPPRIV_H */ + #endif /* __APPLE__ */ + ++#ifdef WITH_LSPP ++#include <libaudit.h> ++#include <selinux/selinux.h> ++#include <selinux/context.h> ++#include <selinux/avc.h> ++#include <selinux/flask.h> ++#include <selinux/av_permissions.h> ++#endif /* WITH_LSPP */ + + /* + * Local functions... +@@ -157,6 +169,9 @@ static void cancel_all_jobs(cupsd_client + static void cancel_job(cupsd_client_t *con, ipp_attribute_t *uri); + static void cancel_subscription(cupsd_client_t *con, int id); + static int check_rss_recipient(const char *recipient); ++#ifdef WITH_LSPP ++static int check_context(cupsd_client_t *con, cupsd_job_t *job); ++#endif /* WITH_LSPP */ + static int check_quotas(cupsd_client_t *con, cupsd_printer_t *p); + static ipp_attribute_t *copy_attribute(ipp_t *to, ipp_attribute_t *attr, + int quickcopy); +@@ -1354,6 +1369,21 @@ add_job(cupsd_client_t *con, /* I - Cl + ipp_attribute_t *media_col, /* media-col attribute */ + *media_margin; /* media-*-margin attribute */ + ipp_t *unsup_col; /* media-col in unsupported response */ ++#ifdef WITH_LSPP ++ char *audit_message; /* Audit message string */ ++ char *printerfile; /* device file pointed to by the printer */ ++ char *userheader = NULL; /* User supplied job-sheets[0] */ ++ char *userfooter = NULL; /* User supplied job-sheets[1] */ ++ int override = 0; /* Was a banner overrode on a job */ ++ security_id_t clisid; /* SELinux SID for the client */ ++ security_id_t psid; /* SELinux SID for the printer */ ++ context_t printercon; /* Printer's context string */ ++ struct stat printerstat; /* Printer's stat buffer */ ++ security_context_t devcon; /* Printer's SELinux context */ ++ struct avc_entry_ref avcref; /* Pointer to the access vector cache */ ++ security_class_t tclass; /* Object class for the SELinux check */ ++ access_vector_t avr; /* Access method being requested */ ++#endif /* WITH_LSPP */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))", +@@ -1612,6 +1642,106 @@ add_job(cupsd_client_t *con, /* I - Cl + ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, + "Untitled"); + ++#ifdef WITH_LSPP ++ if (is_lspp_config()) ++ { ++ if (!con->scon || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "add_job: missing classification for connection '%s'!", printer->name); ++ send_ipp_status(con, IPP_INTERNAL_ERROR, _("Missing required security attributes.")); ++ return (NULL); ++ } ++ ++ /* ++ * Perform an access check so that if the user gets feedback at enqueue time ++ */ ++ ++ printerfile = strstr(printer->device_uri, "/dev/"); ++ if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0)) ++ printerfile = printer->device_uri + strlen("file:"); ++ ++ if (printerfile != NULL) ++ { ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: Attempting an access check on printer device %s", ++ printerfile); ++ ++ if (lstat(printerfile, &printerstat) < 0) ++ { ++ if (errno != ENOENT) ++ { ++ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to stat the printer")); ++ return (NULL); ++ } ++ /* ++ * The printer does not exist, so for now assume it's a FileDevice ++ */ ++ tclass = SECCLASS_FILE; ++ avr = FILE__WRITE; ++ } ++ else if (S_ISCHR(printerstat.st_mode)) ++ { ++ tclass = SECCLASS_CHR_FILE; ++ avr = CHR_FILE__WRITE; ++ } ++ else if (S_ISREG(printerstat.st_mode)) ++ { ++ tclass = SECCLASS_FILE; ++ avr = FILE__WRITE; ++ } ++ else ++ { ++ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Printer is not a character device or regular file")); ++ return (NULL); ++ } ++ static avc_initialized = 0; ++ if (!avc_initialized++) ++ avc_init("cupsd_enqueue_", NULL, NULL, NULL, NULL); ++ avc_entry_ref_init(&avcref); ++ if (avc_context_to_sid(con->scon, &clisid) != 0) ++ { ++ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the client")); ++ return (NULL); ++ } ++ if (getfilecon(printerfile, &devcon) == -1) ++ { ++ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux context of the printer")); ++ return (NULL); ++ } ++ printercon = context_new(devcon); ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: printer context %s client context %s", ++ context_str(printercon), con->scon); ++ context_free(printercon); ++ ++ if (avc_context_to_sid(devcon, &psid) != 0) ++ { ++ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("Unable to get the SELinux sid of the printer")); ++ freecon(devcon); ++ return (NULL); ++ } ++ freecon(devcon); ++ if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0) ++ { ++ /* ++ * The access check failed, so cancel the job and send an audit message ++ */ ++ if (AuditLog != -1) ++ { ++ audit_message = NULL; ++ cupsdSetStringf(&audit_message, "job=? auid=%u acct=%s obj=%s refused" ++ " unable to access printer=%s", con->auid, ++ con->username, con->scon, printer->name); ++ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message, ++ ServerName, NULL, NULL, 0); ++ cupsdClearString(&audit_message); ++ } ++ ++ send_ipp_status(con, IPP_NOT_AUTHORIZED, _("SELinux prohibits access to the printer")); ++ return (NULL); ++ } ++ } ++ } ++#endif /* WITH_LSPP */ ++ + if ((job = cupsdAddJob(priority, printer->name)) == NULL) + { + send_ipp_status(con, IPP_INTERNAL_ERROR, +@@ -1620,6 +1750,32 @@ add_job(cupsd_client_t *con, /* I - Cl + return (NULL); + } + ++#ifdef WITH_LSPP ++ if (is_lspp_config()) ++ { ++ /* ++ * duplicate the security context and auid of the connection into the job structure ++ */ ++ job->scon = strdup(con->scon); ++ job->auid = con->auid; ++ ++ /* ++ * add the security context to the request so that on a restart the security ++ * attributes will be able to be restored ++ */ ++ ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "security-context", ++ NULL, job->scon); ++ } ++ else ++ { ++ /* ++ * Fill in the security context of the job as unlabeled ++ */ ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "add_job: setting context of job to %s", UNKNOWN_SL); ++ cupsdSetString(&job->scon, UNKNOWN_SL); ++ } ++#endif /* WITH_LSPP */ ++ + job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | + CUPS_PRINTER_REMOTE); + job->attrs = con->request; +@@ -1825,6 +1981,29 @@ add_job(cupsd_client_t *con, /* I - Cl + attr->values[0].string.text = _cupsStrRetain(printer->job_sheets[0]); + attr->values[1].string.text = _cupsStrRetain(printer->job_sheets[1]); + } ++#ifdef WITH_LSPP ++ else ++ { ++ /* ++ * The option was present, so capture the user supplied strings ++ */ ++ userheader = strdup(attr->values[0].string.text); ++ ++ if (attr->num_values > 1) ++ userfooter = strdup(attr->values[1].string.text); ++ ++ if (Classification != NULL && (strcmp(userheader, Classification) == 0) ++ && userfooter &&(strcmp(userfooter, Classification) == 0)) ++ { ++ /* ++ * Since both values are Classification, the user is not trying to Override ++ */ ++ free(userheader); ++ if (userfooter) free(userfooter); ++ userheader = userfooter = NULL; ++ } ++ } ++#endif /* WITH_LSPP */ + + job->job_sheets = attr; + +@@ -1855,6 +2034,9 @@ add_job(cupsd_client_t *con, /* I - Cl + "job-sheets="%s,none", " + "job-originating-user-name="%s"", + Classification, job->username); ++#ifdef WITH_LSPP ++ override = 1; ++#endif /* WITH_LSPP */ + } + else if (attr->num_values == 2 && + strcmp(attr->values[0].string.text, +@@ -1873,6 +2055,9 @@ add_job(cupsd_client_t *con, /* I - Cl + "job-originating-user-name="%s"", + attr->values[0].string.text, + attr->values[1].string.text, job->username); ++#ifdef WITH_LSPP ++ override = 1; ++#endif /* WITH_LSPP */ + } + else if (strcmp(attr->values[0].string.text, Classification) && + strcmp(attr->values[0].string.text, "none") && +@@ -1893,6 +2078,9 @@ add_job(cupsd_client_t *con, /* I - Cl + "job-originating-user-name="%s"", + attr->values[0].string.text, + attr->values[1].string.text, job->username); ++#ifdef WITH_LSPP ++ override = 1; ++#endif /* WITH_LSPP */ + } + } + else if (strcmp(attr->values[0].string.text, Classification) && +@@ -1933,8 +2121,52 @@ add_job(cupsd_client_t *con, /* I - Cl + "job-sheets="%s", " + "job-originating-user-name="%s"", + Classification, job->username); ++#ifdef WITH_LSPP ++ override = 1; ++#endif /* WITH_LSPP */ ++ } ++#ifdef WITH_LSPP ++ if (is_lspp_config() && AuditLog != -1) ++ { ++ audit_message = NULL; ++ ++ if (userheader || userfooter) ++ { ++ if (!override) ++ { ++ /* ++ * The user overrode the banner, so audit it ++ */ ++ cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s" ++ " using banners=%s,%s", job->id, userheader, ++ userfooter, attr->values[0].string.text, ++ (attr->num_values > 1) ? attr->values[1].string.text : "(null)"); ++ audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message, ++ ServerName, NULL, NULL, 1); ++ } ++ else ++ { ++ /* ++ * The user tried to override the banner, audit the failure ++ */ ++ cupsdSetStringf(&audit_message, "job=%d user supplied job-sheets=%s,%s" ++ " ignored banners=%s,%s", job->id, userheader, ++ userfooter, attr->values[0].string.text, ++ (attr->num_values > 1) ? attr->values[1].string.text : "(null)"); ++ audit_log_user_message(AuditLog, AUDIT_LABEL_OVERRIDE, audit_message, ++ ServerName, NULL, NULL, 0); ++ } ++ cupsdClearString(&audit_message); ++ } + } ++ ++ if (userheader) ++ free(userheader); ++ if (userfooter) ++ free(userfooter); ++#endif /* WITH_LSPP */ + } ++ + + /* + * See if we need to add the starting sheet... +@@ -4289,6 +4521,107 @@ check_rss_recipient( + } + + ++#ifdef WITH_LSPP ++/* ++ * 'check_context()' - Check SELinux security context of a user and job ++ */ ++ ++static int /* O - 1 if OK, 0 if not, -1 on error */ ++check_context(cupsd_client_t *con, /* I - Client connection */ ++ cupsd_job_t *job) /* I - Job */ ++{ ++ int enforcing; /* is SELinux in enforcing mode */ ++ char filename[1024]; /* Filename of the spool file */ ++ security_id_t clisid; /* SELinux SID of the client */ ++ security_id_t jobsid; /* SELinux SID of the job */ ++ security_id_t filesid; /* SELinux SID of the spool file */ ++ struct avc_entry_ref avcref; /* AVC entry cache pointer */ ++ security_class_t tclass; /* SELinux security class */ ++ access_vector_t avr; /* SELinux access being queried */ ++ security_context_t spoolfilecon; /* SELinux context of the spool file */ ++ ++ ++ /* ++ * Validate the input to be sure there are contexts to work with... ++ */ ++ ++ if (con->scon == NULL || job->scon == NULL ++ || strncmp(con->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0 ++ || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0) ++ return -1; ++ ++ if ((enforcing = security_getenforce()) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "Error while determining SELinux enforcement"); ++ return -1; ++ } ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "check_context: client context %s job context %s", con->scon, job->scon); ++ ++ ++ /* ++ * Initialize the avc engine... ++ */ ++ ++ static avc_initialized = 0; ++ if (! avc_initialized++) ++ { ++ if (avc_init("cupsd", NULL, NULL, NULL, NULL) < 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "check_context: unable avc_init"); ++ return -1; ++ } ++ } ++ if (avc_context_to_sid(con->scon, &clisid) != 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "check_context: unable to convert %s to SELinux sid", con->scon); ++ return -1; ++ } ++ avc_context_to_sid(job->scon, &jobsid); ++ avc_entry_ref_init(&avcref); ++ tclass = SECCLASS_FILE; ++ avr = FILE__READ; ++ ++ /* ++ * Perform the check with the client as the subject, first with the job as the object ++ * if that fails then with the spool file as the object... ++ */ ++ ++ if (avc_has_perm_noaudit(clisid, jobsid, tclass, avr, &avcref, NULL) != 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "check_context: SELinux denied access based on the client context"); ++ ++ snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id); ++ if (getfilecon(filename, &spoolfilecon) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "check_context: Unable to get spoolfile context"); ++ return -1; ++ } ++ if (avc_context_to_sid(spoolfilecon, &filesid) != 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "check_context: Unable to determine the SELinux sid for the spool file"); ++ freecon(spoolfilecon); ++ return -1; ++ } ++ freecon(spoolfilecon); ++ if (avc_has_perm_noaudit(clisid, filesid, tclass, avr, &avcref, NULL) != 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_INFO, "check_context: SELinux denied access to the spool file"); ++ return 0; ++ } ++ cupsdLogMessage(CUPSD_LOG_INFO, "check_context: SELinux allowed access to the spool file"); ++ return 1; ++ } ++ else ++ if (enforcing == 0) ++ cupsdLogMessage(CUPSD_LOG_INFO, "check_context: allowing operation due to permissive mode"); ++ else ++ cupsdLogMessage(CUPSD_LOG_INFO, "check_context: SELinux allowed access based on the client context"); ++ ++ return 1; ++} ++#endif /* WITH_LSPP */ ++ ++ + /* + * 'check_quotas()' - Check quotas for a printer and user. + */ +@@ -4843,6 +5176,15 @@ copy_banner(cupsd_client_t *con, /* I - + char attrname[255], /* Name of attribute */ + *s; /* Pointer into name */ + ipp_attribute_t *attr; /* Attribute */ ++#ifdef WITH_LSPP ++ const char *mls_label; /* SL of print job */ ++ char *jobrange; /* SELinux sensitivity range */ ++ char *jobclearance; /* SELinux low end clearance */ ++ context_t jobcon; /* SELinux context of the job */ ++ context_t tmpcon; /* Temp context to set the level */ ++ security_context_t spoolcon; /* Context of the file in the spool */ ++#endif /* WITH_LSPP */ ++ + + + cupsdLogMessage(CUPSD_LOG_DEBUG2, +@@ -4878,6 +5220,82 @@ copy_banner(cupsd_client_t *con, /* I - + + fchmod(cupsFileNumber(out), 0640); + fchown(cupsFileNumber(out), RunUser, Group); ++#ifdef WITH_LSPP ++ if (job->scon != NULL && ++ strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) ++ { ++ if (getfilecon(filename, &spoolcon) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "copy_banner: Unable to get the context of the banner file %s - %s", ++ filename, strerror(errno)); ++ job->num_files --; ++ return (0); ++ } ++ tmpcon = context_new(spoolcon); ++ jobcon = context_new(job->scon); ++ freecon(spoolcon); ++ if (!tmpcon || !jobcon) ++ { ++ if (tmpcon) ++ context_free(tmpcon); ++ if (jobcon) ++ context_free(jobcon); ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "copy_banner: Unable to get the SELinux contexts"); ++ job->num_files --; ++ return (0); ++ } ++ jobrange = context_range_get(jobcon); ++ if (jobrange) ++ { ++ jobrange = strdup(jobrange); ++ if ((jobclearance = strtok(jobrange, "-")) != NULL) ++ { ++ if (context_range_set(tmpcon, jobclearance) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "copy_banner: Unable to set the level of the context for file %s - %s", ++ filename, strerror(errno)); ++ free(jobrange); ++ context_free(jobcon); ++ context_free(tmpcon); ++ job->num_files --; ++ return (0); ++ } ++ } ++ else ++ { ++ if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "copy_banner: Unable to set the level of the context for file %s - %s", ++ filename, strerror(errno)); ++ free(jobrange); ++ context_free(jobcon); ++ context_free(tmpcon); ++ job->num_files --; ++ return (0); ++ } ++ } ++ free(jobrange); ++ } ++ if (setfilecon(filename, context_str(tmpcon)) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "copy_banner: Unable to set the context of the banner file %s - %s", ++ filename, strerror(errno)); ++ context_free(jobcon); ++ context_free(tmpcon); ++ job->num_files --; ++ return (0); ++ } ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_banner: %s set to %s", ++ filename, context_str(tmpcon)); ++ context_free(jobcon); ++ context_free(tmpcon); ++ } ++#endif /* WITH_LSPP */ + + /* + * Try the localized banner file under the subdirectory... +@@ -4972,6 +5390,24 @@ copy_banner(cupsd_client_t *con, /* I - + else + s = attrname; + ++#ifdef WITH_LSPP ++ if (strcmp(s, "mls-label") == 0) ++ { ++ if (job->scon != NULL && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) ++ { ++ jobcon = context_new(job->scon); ++ if (strcasecmp(name, MLS_CONFIG) == 0) ++ mls_label = context_range_get(jobcon); ++ else if (strcasecmp(name, TE_CONFIG) == 0) ++ mls_label = context_type_get(jobcon); ++ else // default to using the whole context string ++ mls_label = context_str(jobcon); ++ cupsFilePuts(out, mls_label); ++ context_free(jobcon); ++ } ++ continue; ++ } ++#endif /* WITH_LSPP */ + if (!strcmp(s, "printer-name")) + { + cupsFilePuts(out, job->dest); +@@ -6945,6 +7381,22 @@ get_job_attrs(cupsd_client_t *con, /* I + return; + } + ++ ++#ifdef WITH_LSPP ++ /* ++ * Check SELinux... ++ */ ++ if (is_lspp_config() && check_context(con, job) != 1) ++ { ++ /* ++ * Unfortunately we have to lie to the user... ++ */ ++ send_ipp_status(con, IPP_NOT_FOUND, _("Job #%d does not exist!"), jobid); ++ return; ++ } ++#endif /* WITH_LSPP */ ++ ++ + /* + * Copy attributes... + */ +@@ -7175,6 +7627,11 @@ get_jobs(cupsd_client_t *con, /* I - C + if (username[0] && strcasecmp(username, job->username)) + continue; + ++#ifdef WITH_LSPP ++ if (is_lspp_config() && check_context(con, job) != 1) ++ continue; ++#endif /* WITH_LSPP */ ++ + if (count > 0) + ippAddSeparator(con->response); + +@@ -11594,6 +12051,11 @@ validate_user(cupsd_job_t *job, /* I + + strlcpy(username, get_username(con), userlen); + ++#ifdef WITH_LSPP ++ if (is_lspp_config() && check_context(con, job) != 1) ++ return 0; ++#endif /* WITH_LSPP */ ++ + /* + * Check the username against the owner... + */ +diff -up cups-1.4.5/scheduler/job.c.lspp cups-1.4.5/scheduler/job.c +--- cups-1.4.5/scheduler/job.c.lspp 2010-12-24 13:21:31.028862162 +0000 ++++ cups-1.4.5/scheduler/job.c 2010-12-24 13:21:31.224857060 +0000 +@@ -66,6 +66,9 @@ + * update_job_attrs() - Update the job-printer-* attributes. + */ + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + /* + * Include necessary headers... + */ +@@ -75,6 +78,14 @@ + #include <cups/backend.h> + #include <cups/dir.h> + ++#ifdef WITH_LSPP ++#include <libaudit.h> ++#include <selinux/selinux.h> ++#include <selinux/context.h> ++#include <selinux/avc.h> ++#include <selinux/flask.h> ++#include <selinux/av_permissions.h> ++#endif /* WITH_LSPP */ + + /* + * Design Notes for Job Management +@@ -505,6 +516,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I + /* PRINTER env variable */ + rip_max_cache[255]; + /* RIP_MAX_CACHE env variable */ ++#ifdef WITH_LSPP ++ char *audit_message = NULL; /* Audit message string */ ++ context_t jobcon; /* SELinux context of the job */ ++ char *label_template = NULL; /* SL to put in classification ++ env var */ ++ const char *mls_label = NULL; /* SL to put in classification ++ env var */ ++#endif /* WITH_LSPP */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG2, +@@ -929,6 +948,67 @@ cupsdContinueJob(cupsd_job_t *job) /* I + } + } + ++#ifdef WITH_LSPP ++ if (is_lspp_config()) ++ { ++ if (!job->scon || strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) == 0) ++ { ++ if (AuditLog != -1) ++ { ++ audit_message = NULL; ++ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s", ++ job->id, job->auid, job->username, job->printer->name, title); ++ audit_log_user_message(AuditLog, AUDIT_USER_UNLABELED_EXPORT, audit_message, ++ ServerName, NULL, NULL, 1); ++ cupsdClearString(&audit_message); ++ } ++ } ++ else ++ { ++ jobcon = context_new(job->scon); ++ ++ if ((attr = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME)) == NULL) ++ label_template = strdup(Classification); ++ else if (attr->num_values > 1 && ++ strcmp(attr->values[1].string.text, "none") != 0) ++ label_template = strdup(attr->values[1].string.text); ++ else ++ label_template = strdup(attr->values[0].string.text); ++ ++ if (strcasecmp(label_template, MLS_CONFIG) == 0) ++ mls_label = context_range_get(jobcon); ++ else if (strcasecmp(label_template, TE_CONFIG) == 0) ++ mls_label = context_type_get(jobcon); ++ else if (strcasecmp(label_template, SELINUX_CONFIG) == 0) ++ mls_label = context_str(jobcon); ++ else ++ mls_label = label_template; ++ ++ if (mls_label && (PerPageLabels || banner_page)) ++ { ++ snprintf(classification, sizeof(classification), "CLASSIFICATION=LSPP:%s", mls_label); ++ envp[envc ++] = classification; ++ } ++ ++ if ((AuditLog != -1) && !banner_page) ++ { ++ audit_message = NULL; ++ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s printer=%s title=%s" ++ " obj=%s label=%s", job->id, job->auid, job->username, ++ job->printer->name, title, job->scon, mls_label?mls_label:"none"); ++ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message, ++ ServerName, NULL, NULL, 1); ++ cupsdClearString(&audit_message); ++ } ++ context_free(jobcon); ++ free(label_template); ++ } ++ } ++ else ++ /* ++ * Fall through to the non-LSPP behavior ++ */ ++#endif /* WITH_LSPP */ + if (Classification && !banner_page) + { + if ((attr = ippFindAttribute(job->attrs, "job-sheets", +@@ -1165,13 +1245,13 @@ cupsdContinueJob(cupsd_job_t *job) /* I + if (access(command, F_OK)) + { + snprintf(command, sizeof(command), "%s/backend/%s", ServerBin_compat, +- method); ++ scheme); + if (!access(command, F_OK)) + { + /* Not in the correct directory, but we found it in the compat + * directory. Issue a warning. */ + cupsdLogMessage(CUPSD_LOG_INFO, +- "Backend '%s' not in %s/backend!", method, ++ "Backend '%s' not in %s/backend!", scheme, + ServerBin); + } + else +@@ -1179,7 +1259,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I + /* Not in the compat directory either; make any error + messages use the correct directory name then. */ + snprintf(command, sizeof(command), "%s/backend/%s", ServerBin, +- method); ++ scheme); + } + } + #endif /* __x86_64__ */ +@@ -1626,6 +1706,20 @@ cupsdLoadJob(cupsd_job_t *job) /* I - J + goto error; + } + ++#ifdef WITH_LSPP ++ if ((attr = ippFindAttribute(job->attrs, "security-context", IPP_TAG_NAME)) != NULL) ++ cupsdSetString(&job->scon, attr->values[0].string.text); ++ else if (is_lspp_config()) ++ { ++ /* ++ * There was no security context so delete the job ++ */ ++ cupsdLogMessage(CUPSD_LOG_ERROR, "LoadAllJobs: Missing or bad security-context attribute in control file "%s"!", ++ jobfile); ++ goto error; ++ } ++#endif /* WITH_LSPP */ ++ + job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed", + IPP_TAG_INTEGER); + job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME); +@@ -2013,6 +2107,14 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J + { + char filename[1024]; /* Job control filename */ + cups_file_t *fp; /* Job file */ ++#ifdef WITH_LSPP ++ security_context_t spoolcon; /* context of the job control file */ ++ context_t jobcon; /* contex_t container for job->scon */ ++ context_t tmpcon; /* Temp context to swap the level */ ++ char *jobclearance; /* SELinux low end clearance */ ++ const char *jobrange; /* SELinux sensitivity range */ ++ char *jobrange_copy; /* SELinux sensitivity range */ ++#endif /* WITH_LSPP */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSaveJob(job=%p(%d)): job->attrs=%p", +@@ -2031,6 +2133,76 @@ cupsdSaveJob(cupsd_job_t *job) /* I - J + fchmod(cupsFileNumber(fp), 0600); + fchown(cupsFileNumber(fp), RunUser, Group); + ++#ifdef WITH_LSPP ++ if (job->scon && strncmp(job->scon, UNKNOWN_SL, strlen(UNKNOWN_SL)) != 0) ++ { ++ if (getfilecon(filename, &spoolcon) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "Unable to get context of job control file "%s" - %s.", ++ filename, strerror(errno)); ++ return; ++ } ++ jobcon = context_new(job->scon); ++ tmpcon = context_new(spoolcon); ++ freecon(spoolcon); ++ if (!jobcon || !tmpcon) ++ { ++ if (jobcon) ++ context_free(jobcon); ++ if (tmpcon) ++ context_free(tmpcon); ++ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get SELinux contexts"); ++ return; ++ } ++ jobrange = context_range_get(jobcon); ++ if (jobrange) ++ { ++ jobrange_copy = strdup(jobrange); ++ if ((jobclearance = strtok(jobrange_copy, "-")) != NULL) ++ { ++ if (context_range_set(tmpcon, jobclearance) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "Unable to set the range for job control file "%s" - %s.", ++ filename, strerror(errno)); ++ free(jobrange_copy); ++ context_free(tmpcon); ++ context_free(jobcon); ++ return; ++ } ++ } ++ else ++ { ++ if (context_range_set(tmpcon, (context_range_get(jobcon))) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "Unable to set the range for job control file "%s" - %s.", ++ filename, strerror(errno)); ++ free(jobrange_copy); ++ context_free(tmpcon); ++ context_free(jobcon); ++ return; ++ } ++ } ++ free(jobrange_copy); ++ } ++ if (setfilecon(filename, context_str(tmpcon)) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "Unable to set context of job control file "%s" - %s.", ++ filename, strerror(errno)); ++ context_free(tmpcon); ++ context_free(jobcon); ++ return; ++ } ++ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSaveJob(job=%p): new spool file context=%s", ++ job, context_str(tmpcon)); ++ context_free(tmpcon); ++ context_free(jobcon); ++ } ++#endif /* WITH_LSPP */ ++ + job->attrs->state = IPP_IDLE; + + if (ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL, +@@ -3332,6 +3504,18 @@ get_options(cupsd_job_t *job, /* I - Jo + banner_page) + continue; + ++#ifdef WITH_LSPP ++ /* ++ * In LSPP mode refuse to honor the page-label ++ */ ++ if (is_lspp_config() && ++ !strcmp(attr->name, "page-label")) ++ { ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Ignoring page-label option due to LSPP mode"); ++ continue; ++ } ++#endif /* WITH_LSPP */ ++ + /* + * Otherwise add them to the list... + */ +@@ -4020,6 +4204,19 @@ static void + start_job(cupsd_job_t *job, /* I - Job ID */ + cupsd_printer_t *printer) /* I - Printer to print job */ + { ++#ifdef WITH_LSPP ++ char *audit_message = NULL; /* Audit message string */ ++ char *printerfile = NULL; /* Device file pointed to by the printer */ ++ security_id_t clisid; /* SELinux SID for the client */ ++ security_id_t psid; /* SELinux SID for the printer */ ++ context_t printercon; /* Printer's context string */ ++ struct stat printerstat; /* Printer's stat buffer */ ++ security_context_t devcon; /* Printer's SELinux context */ ++ struct avc_entry_ref avcref; /* Pointer to the access vector cache */ ++ security_class_t tclass; /* Object class for the SELinux check */ ++ access_vector_t avr; /* Access method being requested */ ++#endif /* WITH_LSPP */ ++ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job(job=%p(%d), printer=%p(%s))", + job, job->id, printer, printer->name); + +@@ -4142,6 +4339,108 @@ start_job(cupsd_job_t *job, /* I - + fcntl(job->side_pipes[1], F_SETFD, + fcntl(job->side_pipes[1], F_GETFD) | FD_CLOEXEC); + ++#ifdef WITH_LSPP ++ if (is_lspp_config()) ++ { ++ /* ++ * Perform an access check before printing, but only if the printer starts with /dev/ ++ */ ++ printerfile = strstr(printer->device_uri, "/dev/"); ++ if (printerfile == NULL && (strncmp(printer->device_uri, "file:/", 6) == 0)) ++ printerfile = printer->device_uri + strlen("file:"); ++ ++ if (printerfile != NULL) ++ { ++ cupsdLogMessage(CUPSD_LOG_DEBUG, ++ "StartJob: Attempting to check access on printer device %s", printerfile); ++ if (lstat(printerfile, &printerstat) < 0) ++ { ++ if (errno != ENOENT) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "StartJob: Unable to stat the printer"); ++ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); ++ return ; ++ } ++ /* ++ * The printer does not exist, so for now assume it's a FileDevice ++ */ ++ tclass = SECCLASS_FILE; ++ avr = FILE__WRITE; ++ } ++ else if (S_ISCHR(printerstat.st_mode)) ++ { ++ tclass = SECCLASS_CHR_FILE; ++ avr = CHR_FILE__WRITE; ++ } ++ else if (S_ISREG(printerstat.st_mode)) ++ { ++ tclass = SECCLASS_FILE; ++ avr = FILE__WRITE; ++ } ++ else ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "StartJob: Printer is not a character device or regular file"); ++ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); ++ return ; ++ } ++ static avc_initialized = 0; ++ if (!avc_initialized++) ++ avc_init("cupsd_dequeue_", NULL, NULL, NULL, NULL); ++ avc_entry_ref_init(&avcref); ++ if (avc_context_to_sid(job->scon, &clisid) != 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "StartJob: Unable to determine the SELinux sid for the job"); ++ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); ++ return ; ++ } ++ if (getfilecon(printerfile, &devcon) == -1) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "StartJob: Unable to get the SELinux context of %s", ++ printerfile); ++ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); ++ return ; ++ } ++ printercon = context_new(devcon); ++ cupsdLogMessage(CUPSD_LOG_DEBUG, "StartJob: printer context %s client context %s", ++ context_str(printercon), job->scon); ++ context_free(printercon); ++ ++ if (avc_context_to_sid(devcon, &psid) != 0) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, ++ "StartJob: Unable to determine the SELinux sid for the printer"); ++ freecon(devcon); ++ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); ++ return ; ++ } ++ freecon(devcon); ++ ++ if (avc_has_perm(clisid, psid, tclass, avr, &avcref, NULL) != 0) ++ { ++ /* ++ * The access check failed, so cancel the job and send an audit message ++ */ ++ if (AuditLog != -1) ++ { ++ audit_message = NULL; ++ cupsdSetStringf(&audit_message, "job=%d auid=%u acct=%s obj=%s canceled" ++ " unable to access printer=%s", job->id, ++ job->auid, (job->username)?job->username:"?", job->scon, printer->name); ++ audit_log_user_message(AuditLog, AUDIT_USER_LABELED_EXPORT, audit_message, ++ ServerName, NULL, NULL, 0); ++ cupsdClearString(&audit_message); ++ } ++ ++ cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_DEFAULT, NULL); ++ ++ return ; ++ } ++ } ++ } ++#endif /* WITH_LSPP */ ++ + /* + * Now start the first file in the job... + */ +diff -up cups-1.4.5/scheduler/job.h.lspp cups-1.4.5/scheduler/job.h +--- cups-1.4.5/scheduler/job.h.lspp 2009-05-11 23:46:01.000000000 +0100 ++++ cups-1.4.5/scheduler/job.h 2010-12-24 13:21:31.225857034 +0000 +@@ -13,6 +13,13 @@ + * file is missing or damaged, see the license at "http://www.cups.org/". + */ + ++/* Copyright (C) 2005 Trusted Computer Solutions, Inc. */ ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ ++#ifdef WITH_LSPP ++#include <selinux/selinux.h> ++#endif /* WITH_LSPP */ ++ + /* + * Constants... + */ +@@ -83,6 +90,10 @@ struct cupsd_job_s /**** Job request * + krb5_ccache ccache; /* Kerberos credential cache */ + char *ccname; /* KRB5CCNAME environment variable */ + #endif /* HAVE_GSSAPI */ ++#ifdef WITH_LSPP ++ security_context_t scon; /* Security context of job */ ++ uid_t auid; /* Audit loginuid for this job */ ++#endif /* WITH_LSPP */ + }; + + typedef struct cupsd_joblog_s /**** Job log message ****/ +diff -up cups-1.4.5/scheduler/main.c.lspp cups-1.4.5/scheduler/main.c +--- cups-1.4.5/scheduler/main.c.lspp 2010-12-24 13:21:31.158858778 +0000 ++++ cups-1.4.5/scheduler/main.c 2010-12-24 13:22:10.827825881 +0000 +@@ -37,6 +37,8 @@ + * usage() - Show scheduler usage. + */ + ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + /* + * Include necessary headers... + */ +@@ -76,6 +78,9 @@ + # include <dlfcn.h> + #endif /* __APPLE__ && HAVE_DLFCN_H */ + ++#ifdef WITH_LSPP ++# include <libaudit.h> ++#endif /* WITH_LSPP */ + + /* + * Local functions... +@@ -145,6 +150,9 @@ main(int argc, /* I - Number of comm + #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ + #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ ++#if WITH_LSPP ++ auditfail_t failmode; /* Action for audit_open failure */ ++#endif /* WITH_LSPP */ + #ifdef __sgi + cups_file_t *fp; /* Fake lpsched lock file */ + struct stat statbuf; /* Needed for checking lpsched FIFO */ +@@ -474,6 +482,25 @@ main(int argc, /* I - Number of comm + #endif /* DEBUG */ + } + ++#ifdef WITH_LSPP ++ if ((AuditLog = audit_open()) < 0 ) ++ { ++ if (get_auditfail_action(&failmode) == 0) ++ { ++ if (failmode == FAIL_LOG) ++ { ++ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to connect to audit subsystem."); ++ AuditLog = -1; ++ } ++ else if (failmode == FAIL_TERMINATE) ++ { ++ fprintf(stderr, "cupsd: unable to start auditing, terminating"); ++ return -1; ++ } ++ } ++ } ++#endif /* WITH_LSPP */ ++ + /* + * Set the timezone info... + */ +@@ -1241,6 +1268,11 @@ main(int argc, /* I - Number of comm + + cupsdStopSelect(); + ++#ifdef WITH_LSPP ++ if (AuditLog != -1) ++ audit_close(AuditLog); ++#endif /* WITH_LSPP */ ++ + return (!stop_scheduler); + } + +diff -up cups-1.4.5/scheduler/printers.c.lspp cups-1.4.5/scheduler/printers.c +--- cups-1.4.5/scheduler/printers.c.lspp 2010-12-24 13:21:31.168858518 +0000 ++++ cups-1.4.5/scheduler/printers.c 2010-12-24 13:21:31.236856747 +0000 +@@ -59,6 +59,8 @@ + * write_xml_string() - Write a string with XML escaping. + */ + ++/* (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P. */ ++ + /* + * Include necessary headers... + */ +@@ -103,6 +105,10 @@ static void write_irix_state(cupsd_print + #endif /* __sgi */ + static void write_xml_string(cups_file_t *fp, const char *s); + ++#ifdef WITH_LSPP ++# include <libaudit.h> ++# include <selinux/context.h> ++#endif /* WITH_LSPP */ + + /* + * 'cupsdAddPrinter()' - Add a printer to the system. +@@ -2267,6 +2273,13 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) + "username", + "password" + }; ++#ifdef WITH_LSPP ++ char *audit_message; /* Audit message string */ ++ char *printerfile; /* Path to a local printer dev */ ++ char *rangestr; /* Printer's range if its available */ ++ security_context_t devcon; /* Printer SELinux context */ ++ context_t printercon; /* context_t for the printer */ ++#endif /* WITH_LSPP */ + + + DEBUG_printf(("cupsdSetPrinterAttrs: entering name = %s, type = %x\n", p->name, +@@ -2397,6 +2410,45 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p) + attr->values[1].string.text = _cupsStrAlloc(Classification ? + Classification : p->job_sheets[1]); + } ++#ifdef WITH_LSPP ++ if (AuditLog != -1) ++ { ++ audit_message = NULL; ++ rangestr = NULL; ++ printercon = 0; ++ printerfile = strstr(p->device_uri, "/dev/"); ++ if (printerfile == NULL && (strncmp(p->device_uri, "file:/", 6) == 0)) ++ printerfile = p->device_uri + strlen("file:"); ++ ++ if (printerfile != NULL) ++ { ++ if (getfilecon(printerfile, &devcon) == -1) ++ { ++ if(is_selinux_enabled()) ++ cupsdLogMessage(CUPSD_LOG_ERROR, "cupsdSetPrinterAttrs: Unable to get printer context"); ++ } ++ else ++ { ++ printercon = context_new(devcon); ++ freecon(devcon); ++ } ++ } ++ ++ if (printercon && context_range_get(printercon)) ++ rangestr = strdup(context_range_get(printercon)); ++ else ++ rangestr = strdup("unknown"); ++ ++ cupsdSetStringf(&audit_message, "printer=%s uri=%s banners=%s,%s range=%s", ++ p->name, p->sanitized_device_uri, p->job_sheets[0], p->job_sheets[1], rangestr); ++ audit_log_user_message(AuditLog, AUDIT_LABEL_LEVEL_CHANGE, audit_message, ++ ServerName, NULL, NULL, 1); ++ if (printercon) ++ context_free(printercon); ++ free(rangestr); ++ cupsdClearString(&audit_message); ++ } ++#endif /* WITH_LSPP */ + } + + p->raw = 0; +@@ -5536,7 +5588,6 @@ write_irix_state(cupsd_printer_t *p) /* + } + #endif /* __sgi */ + +- + /* + * 'write_xml_string()' - Write a string with XML escaping. + */ diff --git a/pkgs/core/libnih/libnih.nm b/pkgs/core/libnih/libnih.nm index 99c6084..a0fc96f 100644 --- a/pkgs/core/libnih/libnih.nm +++ b/pkgs/core/libnih/libnih.nm @@ -25,7 +25,7 @@ include $(PKGROOT)/Include
PKG_NAME = libnih -PKG_VER = 1.0.2 +PKG_VER = 1.0.3 PKG_REL = 0
PKG_MAINTAINER = Stefan Schantl stefan.schantl@ipfire.org @@ -34,7 +34,7 @@ PKG_URL = https://launchpad.net/libnih PKG_LICENSE = GPL2+ PKG_SUMMARY = Small library with advanced functions.
-PKG_BUILD_DEPS+= dbus-devel pkg-config +PKG_BUILD_DEPS+= dbus-devel expat-devel pkg-config
define PKG_DESCRIPTION libnih is a small library for C application development containing \ @@ -49,8 +49,7 @@ PKG_PACKAGES += $(PKG_NAME)-devel CONFIGURE_OPTIONS += \ --libdir=/lib
-# Testsuite fails -# Testing nih_child_poll() ...with exec by traced child hangs forever. +# Testsuite still fails - 3 tests fail #define STAGE_TEST # cd $(DIR_APP) && make check #endef diff --git a/pkgs/core/libnih/patches/libnih-1.0.2-upstream-1.patch b/pkgs/core/libnih/patches/libnih-1.0.2-upstream-1.patch deleted file mode 100644 index 50d257a..0000000 --- a/pkgs/core/libnih/patches/libnih-1.0.2-upstream-1.patch +++ /dev/null @@ -1,246 +0,0 @@ ---- libnih-1.0.2.orig/debian/libnih-dbus-dev.install -+++ libnih-1.0.2/debian/libnih-dbus-dev.install -@@ -0,0 +1,6 @@ -+lib/libnih-dbus.a -+lib/libnih-dbus.la -+lib/libnih-dbus.so -+usr/include/libnih-dbus.h -+usr/include/nih-dbus -+usr/lib/pkgconfig/libnih-dbus.pc ---- libnih-1.0.2.orig/debian/control -+++ libnih-1.0.2/debian/control -@@ -0,0 +1,65 @@ -+Source: libnih -+Section: libs -+Priority: required -+Maintainer: Scott James Remnant scott@ubuntu.com -+Standards-Version: 3.8.4.0 -+Build-Depends: debhelper (>= 7.3.15), pkg-config (>= 0.22), libdbus-1-dev (>= 1.2.16), libexpat1-dev (>= 2.0.0), dbus (>= 1.2.16) -+ -+Package: libnih1 -+Architecture: any -+Depends: ${shlibs:Depends}, ${misc:Depends} -+Description: NIH Utility Library -+ libnih is a light-weight "standard library" of C functions to ease the -+ development of other libraries and applications, especially those -+ normally found in /lib. -+ . -+ This package contains the shared library. -+ -+Package: libnih-dev -+Priority: optional -+Section: libdevel -+Architecture: any -+Depends: libnih1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} -+Description: NIH Utility Library (development files) -+ libnih is a light-weight "standard library" of C functions to ease the -+ development of other libraries and applications, especially those -+ normally found in /lib. -+ . -+ This package contains the static library and C header files which are -+ needed for developing software using libnih. -+ -+Package: libnih-dbus1 -+Architecture: any -+Depends: libnih1 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} -+Description: NIH D-Bus Bindings Library -+ libnih-dbus is a D-Bus bindings library that integrates with the main -+ loop provided by libnih. -+ . -+ This package contains the shared library. -+ -+Package: libnih-dbus-dev -+Priority: optional -+Section: libdevel -+Architecture: any -+Depends: libnih-dbus1 (= ${binary:Version}), libnih-dev (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} -+Recommends: nih-dbus-tool (= ${binary:Version}) -+Description: NIH D-Bus Bindings Library (development files) -+ libnih-dbus is a D-Bus bindings library that integrates with the main -+ loop provided by libnih. -+ . -+ This package contains the static library and C header files which are -+ needed for developing software using libnih-dbus. -+ -+Package: nih-dbus-tool -+Priority: required -+Section: devel -+Architecture: any -+Depends: ${shlibs:Depends}, ${misc:Depends} -+Recommends: libnih-dbus-dev (= ${binary:Version}) -+Description: NIH D-Bus Binding Tool -+ nih-dbus-tool generates C source code from the D-Bus Introspection XML -+ data provided by most services; either to make implementing the -+ described objects in C programs or to make proxying to the described -+ remote objects easier. -+ . -+ The generated code requires libnih-dbus-dev to be compiled. ---- libnih-1.0.2.orig/debian/libnih-dev.links -+++ libnih-1.0.2/debian/libnih-dev.links -@@ -0,0 +1 @@ -+usr/share/doc/libnih1 usr/share/doc/libnih-dev ---- libnih-1.0.2.orig/debian/libnih-dbus1.install -+++ libnih-1.0.2/debian/libnih-dbus1.install -@@ -0,0 +1 @@ -+lib/libnih-dbus.so.* ---- libnih-1.0.2.orig/debian/nih-dbus-tool.install -+++ libnih-1.0.2/debian/nih-dbus-tool.install -@@ -0,0 +1,2 @@ -+usr/bin/nih-dbus-tool -+usr/share/man/man1/nih-dbus-tool.1 ---- libnih-1.0.2.orig/debian/libnih1.install -+++ libnih-1.0.2/debian/libnih1.install -@@ -0,0 +1 @@ -+lib/libnih.so.* ---- libnih-1.0.2.orig/debian/libnih-dbus1.symbols -+++ libnih-1.0.2/debian/libnih-dbus1.symbols -@@ -0,0 +1,2 @@ -+libnih-dbus.so.1 libnih-dbus1 #MINVER# -+ *@LIBNIH_DBUS_1_0 1.0.0 ---- libnih-1.0.2.orig/debian/libnih1.symbols -+++ libnih-1.0.2/debian/libnih1.symbols -@@ -0,0 +1,2 @@ -+libnih.so.1 libnih1 #MINVER# -+ *@LIBNIH_1_0 1.0.0 ---- libnih-1.0.2.orig/debian/libnih-dev.install -+++ libnih-1.0.2/debian/libnih-dev.install -@@ -0,0 +1,7 @@ -+lib/libnih.a -+lib/libnih.la -+lib/libnih.so -+usr/include/libnih.h -+usr/include/nih -+usr/lib/pkgconfig/libnih.pc -+usr/share/aclocal/libnih.m4 ---- libnih-1.0.2.orig/debian/compat -+++ libnih-1.0.2/debian/compat -@@ -0,0 +1 @@ -+7 ---- libnih-1.0.2.orig/debian/copyright -+++ libnih-1.0.2/debian/copyright -@@ -0,0 +1,18 @@ -+This is the Ubuntu package of libnih, the NIH Utility Library. -+ -+Copyright © 2009 Canonical Ltd. -+Copyright © 2009 Scott James Remnant scott@netsplit.com -+ -+Licence: -+ -+This program is free software; you can redistribute it and/or modify -+it under the terms of the GNU General Public License version 2, as -+published by the Free Software Foundation. -+ -+This program is distributed in the hope that it will be useful, but -+WITHOUT ANY WARRANTY; without even the implied warranty of -+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+General Public License for more details. -+ -+On Ubuntu systems, the complete text of the GNU General Public License -+can be found in ‘/usr/share/common-licenses/GPL’. ---- libnih-1.0.2.orig/debian/libnih-dbus1.links -+++ libnih-1.0.2/debian/libnih-dbus1.links -@@ -0,0 +1 @@ -+usr/share/doc/libnih1 usr/share/doc/libnih-dbus1 ---- libnih-1.0.2.orig/debian/rules -+++ libnih-1.0.2/debian/rules -@@ -0,0 +1,35 @@ -+#!/usr/bin/make -f -+%: -+ dh $@ -+ -+ -+CFLAGS = -Wall -g -fstack-protector -fPIE -+LDFLAGS = -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -pie -+ -+# Disable optimisations if noopt found in $DEB_BUILD_OPTIONS -+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) -+ CFLAGS += -O0 -+ LDFLAGS += -Wl,-O0 -+else -+ CFLAGS += -Os -+ LDFLAGS += -Wl,-O1 -+endif -+ -+override_dh_auto_configure: -+ dh_auto_configure -- CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \ -+ --libdir=/lib -+ -+override_dh_makeshlibs: -+ dh_makeshlibs -plibnih1 -V 'libnih1 (>= 1.0.0)' -+ dh_makeshlibs -plibnih-dbus1 -V 'libnih-dbus1 (>= 1.0.0)' -+ dh_makeshlibs -Nlibnih1 -Nlibnih-dbus1 -+ -+ -+# Symlink /usr/share/doc directories together -+override_dh_installdocs: -+ dh_installdocs -Nlibnih-dev -Nlibnih-dbus1 -Nlibnih-dbus-dev \ -+ -Nnih-dbus-tool -+ -+override_dh_installchangelogs: -+ dh_installchangelogs -Nlibnih-dev -Nlibnih-dbus1 -Nlibnih-dbus-dev \ -+ -Nnih-dbus-tool ---- libnih-1.0.2.orig/debian/libnih1.docs -+++ libnih-1.0.2/debian/libnih1.docs -@@ -0,0 +1,3 @@ -+AUTHORS -+NEWS -+README ---- libnih-1.0.2.orig/debian/changelog -+++ libnih-1.0.2/debian/changelog -@@ -0,0 +1,44 @@ -+libnih (1.0.2-1) maverick; urgency=low -+ -+ * New upstream release: -+ - Rename AC_COPYRIGHT to NIH_COPYRIGHT to avoid conflict with other -+ packages. -+ - Add serial to libnih.m4 -+ - Add NIH_WITH_LOCAL_LIBNIH macro. -+ -+ * Fix use of ${Source-Version} to be ${binary:Version} -+ * Add debian/source/format with "1.0" to be future compatible. -+ * Bump standards version. -+ -+ -- Scott James Remnant scott@ubuntu.com Tue, 27 Apr 2010 10:49:55 -0700 -+ -+libnih (1.0.1-1) lucid; urgency=low -+ -+ * New upstream release: -+ - Add missing __nih_* symbols to linker version script so that we -+ can link Upstart's test suite. -+ - Glibc __abort_msg symbol now only linked as a weak symbol. -+ -+ -- Scott James Remnant scott@ubuntu.com Thu, 04 Feb 2010 14:53:26 -0800 -+ -+libnih (1.0.0-2build1) lucid; urgency=low -+ -+ * Rebuild to pick up relaxed dependency on libc6, after checking that -+ __abort_msg is available with the same signature in eglibc 2.11. -+ LP: #508702. -+ -+ -- Matthias Klose doko@ubuntu.com Mon, 18 Jan 2010 16:09:13 +0100 -+ -+libnih (1.0.0-2) lucid; urgency=low -+ -+ * debian/control: Add build-dependency on dbus so the test suite can -+ pass on the buildds. -+ -+ -- Scott James Remnant scott@ubuntu.com Sat, 28 Nov 2009 23:28:27 +0000 -+ -+libnih (1.0.0-1) lucid; urgency=low -+ -+ * First upstream release. Previously this code was included in the -+ upstart, mountall and ureadahead source packages. -+ -+ -- Scott James Remnant scott@ubuntu.com Sat, 28 Nov 2009 21:14:00 +0000 ---- libnih-1.0.2.orig/debian/nih-dbus-tool.links -+++ libnih-1.0.2/debian/nih-dbus-tool.links -@@ -0,0 +1 @@ -+usr/share/doc/libnih1 usr/share/doc/nih-dbus-tool ---- libnih-1.0.2.orig/debian/libnih-dbus-dev.links -+++ libnih-1.0.2/debian/libnih-dbus-dev.links -@@ -0,0 +1 @@ -+usr/share/doc/libnih1 usr/share/doc/libnih-dbus-dev ---- libnih-1.0.2.orig/debian/source/format -+++ libnih-1.0.2/debian/source/format -@@ -0,0 +1 @@ -+1.0
hooks/post-receive -- IPFire 3.x development tree