Skip to content

Commit

Permalink
Added support for libcups3 (libcups of CUPS 3.x)
Browse files Browse the repository at this point in the history
With these changes libcupsfilters can be built either with libcups2
(libcups of CUPS 2.x) or libcups3 (libcups of CUPS 3.x).

    NOTE: Any further development on the code has to be done using the
    API of libcups3, and for libcups2 support any additional
    conversion has to get defined in cupsfilters/libcups2-private.h
    (if C code is needed for the conversion, it goes into
    cupsfilters/libcups2.c).

The actual code is now fully converted to the API of libcups3. To
allow building it with libcups2 and to avoid having it full of "#ifdef
HAVE_LIBCUPS2" conditionals, we have added the header file
libcups2-private.h file, which gets only applied (by "#ifdef
HAVE_LIBCUPS2") when we build with libcups2.

It converts the code to the libcups2 API by

- Applying "#define ..." macro definitions for all renamings of
  functions and data types

- Converting the "cupsCreateTempFd(NULL, NULL, buffer, bufsize)" calls
  to "cupsTempFd(buffer, bufsize)" calls (new function has more
  arguments).

- Defining (backports) the "http_resolve_t" enumeration data type,
  which got only introduced in libcups3.

- Introducing the type "cups_len_t", as "int" for libcups2 and
  "size_t" for libcups3. In some functions there are parameters which
  make a hard switch from "int" to "size_t" with the transition to
  libcups3. For those we use this type.

We also add the file libcups2.c for the code of our former
"cfResolveURI2()" function, our DNS-SD URI resolver function based on
ipptool which is capable of resolving both print and fax URIs. The
function is only used when building with libcups2, as in libcups3 the
"httpResolveURI()" function which was formerly libcups-internal is now
a public API function, which saves us now from the ugly workarounds we
had to use in our functions."cfResolveURI2()" gets a wrapper calling
this new function then. The code of the print-only "cfResolveURI()"
function got dropped and replaced by a simple call of
"cfResolveURI2()".

We have a libcups3-related change in the public API header files, here
"cups_page_header2_t" got renamed into "cups_page_header_t". Due to
the fact that libcups2-private.h gets HAVE_LIBCUPS2 from config.h, we
cannot use it in the API headers (and we also do not want all these
conversions to apply to a user's code). So we simply add a renaming
"#define ..." under "#if CUPS_VERSION_MAJOR < 3" to the affected API
headers.

We drop support for the old "cups_page_header_t" data type from CUPS
1.x, as with the minimum requirement of CUPS 2.2.2 this is for sure
not needed any more.

We need to pay special attention to "cupsArrayNew()" and
"cupsArrayNew3()" calls in the old libcups2-based code. In the former
ones we keep the name but add ", NULL, 0, NULL, NULL" to the end of
the parameter list, the latter ones get renamed to "cupsArrayNew()"
and the parameter list not changed. For building the code with
libcups2, the "#define cupsArrayNew cupsArrayNew3" then serves for
both cases.

In configure.ac we check for libcups3 via pkg-config first and if not
present for libcups2 via cups-config. In both cases we set all relevan
variables, as compiler/linker arguments, directories, ... and in case
of libcups2 we define HAVE_LIBCUPS2 in config.h.

In Makefile.am we do not only add the new files to the build process
but we also fix the compiler flag definition for C++,
"libcupsfilters_la_CXXFLAGS". It was messed up and the C++ parts did
not build any more with libcups3.
  • Loading branch information
tillkamppeter committed Oct 26, 2023
1 parent 4a2a4cf commit 26f9c3f
Show file tree
Hide file tree
Showing 27 changed files with 710 additions and 525 deletions.
4 changes: 3 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ libcupsfilters_la_SOURCES = \
cupsfilters/imagetopdf.c \
cupsfilters/imagetoraster.c \
cupsfilters/ipp.c \
cupsfilters/libcups2.c \
cupsfilters/libcups2-private.h \
cupsfilters/lut.c \
cupsfilters/mupdftopwg.c \
cupsfilters/pack.c \
Expand Down Expand Up @@ -234,7 +236,7 @@ libcupsfilters_la_LDFLAGS = \
-version-info 2
if BUILD_DBUS
libcupsfilters_la_CFLAGS += $(DBUS_CFLAGS) -DHAVE_DBUS
libcupsfilters_CXXFLAGS = -std=c++0x $(libcupsfilters_CFLAGS) # -std=c++11
libcupsfilters_la_CXXFLAGS = -std=c++11 $(libcupsfilters_la_CFLAGS) # -std=c++11
libcupsfilters_la_LIBADD += $(DBUS_LIBS)
endif

Expand Down
131 changes: 94 additions & 37 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -59,52 +59,102 @@ AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
LT_INIT

# ==========
# pkg-config
# ==========
PKG_PROG_PKG_CONFIG([0.20])
AC_PATH_TOOL([PKGCONFIG], [pkg-config])

AM_GNU_GETTEXT_VERSION([0.18.3])
AM_GNU_GETTEXT([external])

# ================================
# Find CUPS internals (no pc file)
# ================================
AC_ARG_WITH([cups-config],
[AS_HELP_STRING([--with-cups-config=path], [Specify path to cups-config executable.])],
[with_cups_config="$withval"],
[with_cups_config=system]
)

AS_IF([test "x$with_cups_config" != "xsystem"], [
CUPSCONFIG=$with_cups_config
# ====
# CUPS
# ====
AC_MSG_CHECKING([for CUPS library v3.0 or higher])
AS_IF([$PKGCONFIG --exists cups3], [
CUPS_VERSION="$($PKGCONFIG --modversion cups3)"
AC_MSG_RESULT([yes, v$CUPS_VERSION])
CUPS_CFLAGS="$($PKGCONFIG --cflags cups3)"
CUPS_LIBS="$LIBS $($PKGCONFIG --libs cups3)"
AC_SUBST(CUPS_CFLAGS)
AC_SUBST(CUPS_LIBS)
CUPS_DATADIR="$($PKGCONFIG --variable=prefix cups3)/share/cups"
AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$CUPS_DATADIR", [CUPS datadir])
AC_SUBST(CUPS_DATADIR)
AS_IF([test x$host_os_name = xdarwin], [
CUPS_SERVERROOT="/private/etc/cups"
], [
AS_IF([test "x$($PKGCONFIG --variable=prefix cups3)" = x/usr], [
CUPS_SERVERROOT="/etc/cups"
], [
CUPS_SERVERROOT="$($PKGCONFIG --variable=prefix cups3)/etc/cups"
])
])
AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT", [CUPS serverroot])
AC_SUBST(CUPS_SERVERROOT)
CUPS_FONTPATH="$CUPS_DATADIR/fonts"
AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$CUPS_FONTPATH",
[Path to CUPS fonts dir])
AC_SUBST(CUPS_FONTPATH)
CUPS_SERVERBIN="$($PKGCONFIG --variable=prefix cups3)/lib/cups"
AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$CUPS_SERVERBIN",
[Path to CUPS binaries dir])
AC_SUBST(CUPS_SERVERBIN)
], [
AC_MSG_RESULT(no)
AC_ARG_WITH([cups-config],
[AS_HELP_STRING([--with-cups-config=path], [Specify path to cups-config executable.])],
[with_cups_config="$withval"],
[with_cups_config=system])
AS_IF([test "x$with_cups_config" != "xsystem"], [
CUPSCONFIG=$with_cups_config
], [
AC_PATH_TOOL(CUPSCONFIG, [cups-config])
AS_IF([test -z "$CUPSCONFIG"], [
AC_MSG_ERROR([Required cups-config is missing. Please install CUPS developer packages.])
])
])
AC_MSG_CHECKING([for CUPS library v2.x])
AS_IF([test -n "$CUPSCONFIG"], [
CUPS_VERSION=`$CUPSCONFIG --version`
AC_MSG_RESULT([yes, v$CUPS_VERSION])
AC_DEFINE([HAVE_LIBCUPS2], [1], [Use libcups2])
CUPS_CFLAGS=`$CUPSCONFIG --cflags`
CUPS_LIBS=`$CUPSCONFIG --image --libs`
AC_SUBST(CUPS_CFLAGS)
AC_SUBST(CUPS_LIBS)
CUPS_DATADIR="`$CUPSCONFIG --datadir`"
AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$CUPS_DATADIR", [CUPS datadir])
AC_SUBST(CUPS_DATADIR)
CUPS_SERVERROOT="`$CUPSCONFIG --serverroot`"
AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT",
[CUPS serverroot])
AC_SUBST(CUPS_SERVERROOT)
CUPS_FONTPATH="$CUPS_DATADIR/fonts"
AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$CUPS_FONTPATH",
[Path to CUPS fonts dir])
AC_SUBST(CUPS_FONTPATH)
CUPS_SERVERBIN="`$CUPSCONFIG --serverbin`"
AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$CUPS_SERVERBIN",
[Path to CUPS binaries dir])
AC_SUBST(CUPS_SERVERBIN)
], [
AC_MSG_RESULT(no)
AC_MSG_ERROR([Required cups-config is missing. Please install CUPS developer packages.])
])
])
CUPS_CFLAGS=`$CUPSCONFIG --cflags`
CUPS_LIBS=`$CUPSCONFIG --image --libs`
CUPS_VERSION=`$CUPSCONFIG --version`
AC_SUBST(CUPS_CFLAGS)
AC_SUBST(CUPS_LIBS)

CUPS_DATADIR="`$CUPSCONFIG --datadir`"
AC_DEFINE_UNQUOTED(CUPS_DATADIR, "$CUPS_DATADIR", [CUPS datadir])
AC_SUBST(CUPS_DATADIR)

CUPS_SERVERROOT="`$CUPSCONFIG --serverroot`"
AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT", [CUPS serverroot])
AC_SUBST(CUPS_SERVERROOT)

CUPS_FONTPATH="$CUPS_DATADIR/fonts"
AC_DEFINE_UNQUOTED(CUPS_FONTPATH, "$CUPS_FONTPATH", [Path to CUPS fonts dir])
AC_SUBST(CUPS_FONTPATH)

CUPS_SERVERBIN="`$CUPSCONFIG --serverbin`"
AC_DEFINE_UNQUOTED(CUPS_SERVERBIN, "$CUPS_SERVERBIN", [Path to CUPS binaries dir])
AC_SUBST(CUPS_SERVERBIN)

AC_DEFINE(PDFTOPDF, [1], [Needed for pdftopdf filter compilation])
AC_DEFINE_DIR(BANNERTOPDF_DATADIR, "{CUPS_DATADIR}/data", [Directory where bannertopdf finds its data files (PDF templates)])
AC_DEFINE_UNQUOTED(CUPS_SERVERROOT, "$CUPS_SERVERROOT", [Location of CUPS config files])

# Transient run-time state dir of CUPS
CUPS_STATEDIR=""
Expand Down Expand Up @@ -372,6 +422,12 @@ AS_IF([test "x$with_ippfind_path" != "xsystem"], [
])
AC_DEFINE_UNQUOTED([CUPS_IPPFIND], "$CUPS_IPPFIND", [ippfind binary to use.])

# ======================================
# Further needs for the filter functions
# ======================================
AC_DEFINE(PDFTOPDF, [1], [Needed for pdftopdf filter compilation])
AC_DEFINE_DIR(BANNERTOPDF_DATADIR, "{CUPS_DATADIR}/data", [Directory where bannertopdf finds its data files (PDF templates)])

# =========
# Test Font
# =========
Expand Down Expand Up @@ -427,6 +483,7 @@ Environment settings:
CXXFLAGS: ${CXXFLAGS}
LDFLAGS: ${LDFLAGS}
Build configuration:
libcups: ${CUPS_VERSION}
cups-config: ${with_cups_config}
poppler: ${enable_poppler}
ghostscript: ${enable_ghostscript}
Expand Down
12 changes: 6 additions & 6 deletions cupsfilters/bannertopdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
#include <stdarg.h>
#include <math.h>
#include <errno.h>
#include "ipp.h"
#include "ipp.h"
#include "raster.h"
#include <cupsfilters/ipp.h>
#include <cupsfilters/filter.h>
#include <cupsfilters/pdf.h>
#include <cupsfilters/raster.h>
#include <cupsfilters/libcups2-private.h>

#ifndef HAVE_OPEN_MEMSTREAM
#include <fcntl.h>
Expand All @@ -26,8 +28,6 @@
#include <cups/cups.h>
#include <cups/pwg.h>

#include "filter.h"
#include "pdf.h"

typedef enum banner_info_e
{
Expand Down Expand Up @@ -914,7 +914,7 @@ cfFilterBannerToPDF(int inputfd, // I - File descriptor input stream
// Copy the input data stream into a temporary file...
//

if ((tempfd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
if ((tempfd = cupsCreateTempFd(NULL, NULL, tempfile, sizeof(tempfile))) < 0)
{
if (log) log(ld, CF_LOGLEVEL_ERROR,
"cfFilterBannerToPDF: Unable to copy input file: %s",
Expand Down
9 changes: 5 additions & 4 deletions cupsfilters/catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <cups/dir.h>
#include <cups/pwg.h>
#include <cupsfilters/catalog.h>
#include <cupsfilters/libcups2-private.h>


int // O - 1 on success, 0 on failure
Expand Down Expand Up @@ -52,12 +53,12 @@ cfGetURI(const char *url, // I - URL to get
else
encryption = HTTP_ENCRYPTION_IF_REQUESTED;

http = httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 5000, NULL);
http = httpConnect(host, port, NULL, AF_UNSPEC, encryption, 1, 5000, NULL);

if (!http)
return (0);

if ((fd = cupsTempFd(name, (int)namesize)) < 0)
if ((fd = cupsCreateTempFd(NULL, NULL, name, (int)namesize)) < 0)
return (0);

status = cupsGetFd(http, resource, fd);
Expand Down Expand Up @@ -366,7 +367,7 @@ cfCatalogFreeOptionStrings(void* entry,
cups_array_t *
cfCatalogOptionArrayNew()
{
return (cupsArrayNew3(compare_options, NULL, NULL, 0,
return (cupsArrayNew(compare_options, NULL, NULL, 0,
NULL, cfCatalogFreeOptionStrings));
}

Expand Down Expand Up @@ -415,7 +416,7 @@ cfCatalogAddOption(char *name,
if (!opt)
return (NULL);
opt->human_readable = NULL;
opt->choices = cupsArrayNew3(compare_choices, NULL, NULL, 0,
opt->choices = cupsArrayNew(compare_choices, NULL, NULL, 0,
NULL, cfCatalogFreeChoiceStrings);
if (!opt->choices)
{
Expand Down
31 changes: 17 additions & 14 deletions cupsfilters/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <sys/wait.h>
#include <cups/file.h>
#include <cups/array.h>
#include <cupsfilters/libcups2-private.h>


extern char **environ;

Expand Down Expand Up @@ -128,9 +130,9 @@ get_filter_data_ext_entry(cups_array_t *ext_array,
if (!ext_array || !name)
return (NULL);

for (entry = (cf_filter_data_ext_t *)cupsArrayFirst(ext_array);
for (entry = (cf_filter_data_ext_t *)cupsArrayGetFirst(ext_array);
entry;
entry = (cf_filter_data_ext_t *)cupsArrayNext(ext_array))
entry = (cf_filter_data_ext_t *)cupsArrayGetNext(ext_array))
if (strcmp(entry->name, name) == 0)
break;

Expand All @@ -157,7 +159,7 @@ cfFilterDataAddExt(cf_filter_data_t *data, // I - Filter data record
return (NULL);

if (data->extension == NULL)
data->extension = cupsArrayNew(NULL, NULL);
data->extension = cupsArrayNew(NULL, NULL, NULL, 0, NULL, NULL);

if (data->extension == NULL)
return (NULL);
Expand Down Expand Up @@ -214,7 +216,7 @@ cfFilterDataRemoveExt(cf_filter_data_t *data,
cupsArrayRemove(data->extension, entry);
free(entry->name);
free(entry);
if (cupsArrayCount(data->extension) == 0)
if (cupsArrayGetCount(data->extension) == 0)
{
cupsArrayDelete(data->extension);
data->extension = NULL;
Expand Down Expand Up @@ -649,9 +651,9 @@ cfFilterChain(int inputfd, // I - File descriptor input stream
// Remove NULL filters...
//

for (filter = (cf_filter_filter_in_chain_t *)cupsArrayFirst(filter_chain);
for (filter = (cf_filter_filter_in_chain_t *)cupsArrayGetFirst(filter_chain);
filter;
filter = (cf_filter_filter_in_chain_t *)cupsArrayNext(filter_chain))
filter = (cf_filter_filter_in_chain_t *)cupsArrayGetNext(filter_chain))
{
if (!filter->function)
{
Expand All @@ -670,7 +672,7 @@ cfFilterChain(int inputfd, // I - File descriptor input stream
// Empty filter chain -> Pass through the data unchanged
//

if (cupsArrayCount(filter_chain) == 0)
if (cupsArrayGetCount(filter_chain) == 0)
{
if (log) log(ld, CF_LOGLEVEL_INFO,
"cfFilterChain: No filter at all in chain, passing through the data.");
Expand Down Expand Up @@ -698,18 +700,19 @@ cfFilterChain(int inputfd, // I - File descriptor input stream
// Execute all of the filters...
//

pids = cupsArrayNew((cups_array_func_t)compare_filter_pids, NULL);
pids = cupsArrayNew((cups_array_cb_t)compare_filter_pids, NULL,
NULL, 0, NULL, NULL);
current = 0;
filterfds[0][0] = inputfd;
filterfds[0][1] = -1;
filterfds[1][0] = -1;
filterfds[1][1] = -1;

for (filter = (cf_filter_filter_in_chain_t *)cupsArrayFirst(filter_chain);
for (filter = (cf_filter_filter_in_chain_t *)cupsArrayGetFirst(filter_chain);
filter;
filter = next, current = 1 - current)
{
next = (cf_filter_filter_in_chain_t *)cupsArrayNext(filter_chain);
next = (cf_filter_filter_in_chain_t *)cupsArrayGetNext(filter_chain);

if (filterfds[1 - current][0] > 1)
{
Expand Down Expand Up @@ -816,17 +819,17 @@ cfFilterChain(int inputfd, // I - File descriptor input stream

retval = 0;

while (cupsArrayCount(pids) > 0)
while (cupsArrayGetCount(pids) > 0)
{
if ((pid = wait(&status)) < 0)
{
if (errno == EINTR && iscanceled && iscanceled(icd))
{
if (log) log(ld, CF_LOGLEVEL_DEBUG,
"cfFilterChain: Job canceled, killing filters ...");
for (pid_entry = (filter_function_pid_t *)cupsArrayFirst(pids);
for (pid_entry = (filter_function_pid_t *)cupsArrayGetFirst(pids);
pid_entry;
pid_entry = (filter_function_pid_t *)cupsArrayNext(pids))
pid_entry = (filter_function_pid_t *)cupsArrayGetNext(pids))
{
kill(pid_entry->pid, SIGTERM);
free(pid_entry);
Expand Down Expand Up @@ -1102,7 +1105,7 @@ cfFilterExternal(int inputfd, // I - File descriptor input stream
// argument, not via stdin
argv = (char **)calloc(8, sizeof(char *));

fd = cupsTempFd(tmp_name, sizeof(tmp_name));
fd = cupsCreateTempFd(NULL, NULL, tmp_name, sizeof(tmp_name));
if (fd < 0)
{
if (log) log(ld, CF_LOGLEVEL_ERROR,
Expand Down
11 changes: 10 additions & 1 deletion cupsfilters/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ extern "C" {
# include <cups/raster.h>


//
// Renamed CUPS type in API
//

# if CUPS_VERSION_MAJOR < 3
# define cups_page_header_t cups_page_header2_t
# endif


//
// Types and structures...
//
Expand All @@ -58,7 +67,7 @@ typedef struct cf_filter_data_s
ipp_t *job_attrs; // IPP attributes passed along with the job
ipp_t *printer_attrs; // Printer capabilities in IPP format
// (what is answered to get-printer-attributes
cups_page_header2_t *header;
cups_page_header_t *header;
// CUPS/PWG Raster header (optional)
int num_options;
cups_option_t *options; // Job options as key/value pairs
Expand Down
Loading

0 comments on commit 26f9c3f

Please sign in to comment.