├── NEWS ├── m4 └── .gitignore ├── doc ├── version.xml.in ├── man │ └── Makefile.am ├── Makefile.am └── TODO ├── ippd └── Makefile.am ├── data ├── ippd.socket ├── ippd.service.in ├── printerd.service.in ├── org.freedesktop.printerd.service.in ├── org.freedesktop.printerd.conf.in ├── Makefile.am └── org.freedesktop.printerd.policy.in ├── .tx └── config ├── AUTHORS ├── po ├── POTFILES.in ├── en_GB.po ├── en_US.po ├── vi.po ├── es.po ├── tr.po ├── id.po ├── pt_BR.po ├── pt.po ├── uk.po └── fr.po ├── docker └── run-printerd.sh ├── printerd ├── printerd.pc.in ├── printerd-pygi-example.py ├── pd-enumtypes.h.template ├── pd-enumtypes.c.template ├── pd-types.h ├── printerd.h ├── pd-error.h ├── pd-error.c ├── pd-client.h ├── pd-enums.h └── Makefile.am ├── DOCKER.md ├── tests ├── python1 │ ├── Manager.GetPrinters.py │ └── run-test ├── stop-session-service │ └── run-test ├── version │ └── run-test ├── started │ └── run-test ├── start-session-service.sh ├── Manager.GetPrinters │ └── run-test ├── createprinter2 │ └── run-test ├── updatedriver1 │ └── run-test ├── createprinter5 │ └── run-test ├── createprinter1 │ └── run-test ├── job4 │ └── run-test ├── job1 │ └── run-test ├── createprinter3 │ └── run-test ├── filter1 │ └── run-test ├── filter2 │ └── run-test ├── job2 │ └── run-test ├── job3 │ └── run-test └── common.sh ├── autogen.sh ├── .travis.yml ├── tools ├── Makefile.am └── pd-view.py ├── TESTS.md ├── src ├── pd-common.h ├── pd-device-impl.h ├── pd-manager-impl.h ├── pd-job-impl.h ├── pd-daemontypes.h ├── pd-daemon.h ├── pd-printer-impl.h ├── Makefile.am ├── pd-engine.h ├── pd-log.h ├── main.c ├── pd-common.c ├── pd-device-impl.c ├── pd-manager-impl.c └── pd-daemon.c ├── Dockerfile ├── contrib └── printerd.spec.in ├── README.md ├── configure.ac ├── Makefile.am └── git.mk /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | *.m4 2 | -------------------------------------------------------------------------------- /doc/version.xml.in: -------------------------------------------------------------------------------- 1 | @VERSION@ 2 | -------------------------------------------------------------------------------- /doc/man/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | -include $(top_srcdir)/git.mk 3 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | SUBDIRS = \ 3 | man 4 | 5 | -include $(top_srcdir)/git.mk 6 | -------------------------------------------------------------------------------- /ippd/Makefile.am: -------------------------------------------------------------------------------- 1 | libexec_SCRIPTS = ippd 2 | 3 | ippd: ippd.py 4 | cp -a $< $@ 5 | 6 | DISTCLEANFILES=ippd 7 | -------------------------------------------------------------------------------- /data/ippd.socket: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=IPP Daemon socket 3 | 4 | [Socket] 5 | ListenStream=631 6 | 7 | [Install] 8 | WantedBy=sockets.target 9 | -------------------------------------------------------------------------------- /data/ippd.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=IPP Daemon 3 | 4 | [Service] 5 | ExecStart=@libexecdir@/ippd 6 | StandardOutput=syslog 7 | StandardError=syslog 8 | -------------------------------------------------------------------------------- /data/printerd.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Printer Daemon 3 | 4 | [Service] 5 | Type=dbus 6 | BusName=org.freedesktop.printerd 7 | ExecStart=@libexecdir@/printerd 8 | -------------------------------------------------------------------------------- /data/org.freedesktop.printerd.service.in: -------------------------------------------------------------------------------- 1 | [D-BUS Service] 2 | Name=org.freedesktop.printerd 3 | Exec=@libexecdir@/printerdd 4 | User=root 5 | SystemdService=printerd.service 6 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | 4 | [printerd.master] 5 | file_filter = po/.po 6 | source_file = po/printerd.pot 7 | source_lang = en 8 | type = PO 9 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Richard Hughes 2 | Tim Waugh 3 | 4 | A lot of the boilerplate code has been taken from udisks2, which was 5 | written by David Zeuthen 6 | -------------------------------------------------------------------------------- /po/POTFILES.in: -------------------------------------------------------------------------------- 1 | data/org.freedesktop.printerd.policy.in 2 | src/main.c 3 | src/pd-device-impl.c 4 | src/pd-engine.c 5 | src/pd-job-impl.c 6 | src/pd-manager-impl.c 7 | src/pd-printer-impl.c 8 | tools/pd-cli.c 9 | -------------------------------------------------------------------------------- /docker/run-printerd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Start our own system D-Bus 4 | dbus-daemon --system --fork 5 | 6 | # Start up ippd 7 | /usr/libexec/ippd & 8 | 9 | # Start up printerd 10 | exec /usr/libexec/printerd -v 11 | -------------------------------------------------------------------------------- /printerd/printerd.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: printerd Library 7 | Description: printerd Client Library 8 | Version: @VERSION@ 9 | Requires: gio-2.0,gobject-2.0,glib-2.0 10 | Libs: -L${libdir} -lprinterd 11 | Cflags: -I${includedir}/printerd 12 | -------------------------------------------------------------------------------- /DOCKER.md: -------------------------------------------------------------------------------- 1 | Docker container 2 | ================ 3 | 4 | You can build and run printerd inside a docker container. 5 | 6 | Here is to build it: 7 | 8 | $ docker build -t printerd --rm . 9 | 10 | To run it: 11 | 12 | $ docker run -d -p 631:631/tcp printerd 13 | 14 | Doing this is only of limited use for the moment as the IPP interface 15 | is largely unimplemented. 16 | -------------------------------------------------------------------------------- /tests/python1/Manager.GetPrinters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | from gi.repository import printerd 3 | client = printerd.Client.new_sync () 4 | objmgr = client.get_object_manager () 5 | mgr = objmgr.\ 6 | get_object ("/org/freedesktop/printerd/Manager").\ 7 | get_interface ("org.freedesktop.printerd.Manager") 8 | printers = mgr.call_get_printers_sync () 9 | for printer in printers: 10 | print (printer) 11 | -------------------------------------------------------------------------------- /printerd/printerd-pygi-example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # very simple example 4 | 5 | from gi.repository import printerd 6 | 7 | client = printerd.Client.new_sync(None) 8 | manager = client.get_object_manager() 9 | objects = manager.get_objects() 10 | for o in objects: 11 | print '%s:'%o.get_object_path() 12 | ifaces = o.get_interfaces() 13 | for i in ifaces: 14 | print ' IFace %s'%i.get_info().name 15 | print '' 16 | 17 | -------------------------------------------------------------------------------- /tests/stop-session-service/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | PID=$(cat "${top_builddir}/printerd-session.pid") 6 | kill -INT "$PID" 7 | 8 | RET=1 9 | for i in 1 2 3 4 5; do 10 | sleep 1 11 | if kill -0 "$PID" 2>/dev/null; then :; else 12 | RET=0 13 | rm "${top_builddir}/printerd-session.pid" 14 | break 15 | fi 16 | done 17 | 18 | cat "${top_builddir}"/printerd-session.log 19 | result_is "$RET" 20 | -------------------------------------------------------------------------------- /tests/version/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | VERSION="$(grep -w VERSION ${top_builddir}/config.h | cut -d\" -f2)" 6 | Version=$(gdbus call --session \ 7 | --dest org.freedesktop.printerd \ 8 | --object-path /org/freedesktop/printerd/Manager \ 9 | --method org.freedesktop.DBus.Properties.Get \ 10 | org.freedesktop.printerd.Manager \ 11 | Version |\ 12 | cut -d\' -f2) 13 | 14 | test "$VERSION" = "$Version" 15 | result_is $? 16 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to generate all the initial makefiles, etc. 3 | 4 | srcdir=`dirname $0` 5 | test -z "$srcdir" && srcdir=. 6 | 7 | PKG_NAME="printerd" 8 | 9 | (test -f $srcdir/src/Makefile.am) || { 10 | echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" 11 | echo " top-level $PKG_NAME directory" 12 | exit 1 13 | } 14 | 15 | which gnome-autogen.sh || { 16 | echo "You need to install gnome-common" 17 | exit 1 18 | } 19 | 20 | . gnome-autogen.sh --enable-gtk-doc $* 21 | -------------------------------------------------------------------------------- /tests/started/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Just check the logs since start-up for warnings/errors. 6 | printf 0 > "${BOOKMARK}" 7 | 8 | # Is the service running? 9 | PID=$(cat "${top_builddir}/printerd-session.pid") 10 | if ! kill -0 "$PID" 2>/dev/null; then 11 | rm "${top_builddir}/printerd-session.pid" 12 | printf "printerd should be running but is not, log follows:\n" 13 | cat "${top_builddir}/printerd-session.log" 14 | result_is 1 15 | fi 16 | 17 | result_is 0 18 | -------------------------------------------------------------------------------- /doc/TODO: -------------------------------------------------------------------------------- 1 | * Persistence using sqlite 2 | * Service termination when no clients or jobs running 3 | * D-Bus interface needs some tweaks to allow IPP to run on top of it 4 | (e.g. handling option conflicts) 5 | * Device scanning 6 | * Prevent writes to read-only attributes 7 | * Driver selection/assignment, e.g. 8 | http://cyberelk.net/tim/2010/10/26/choosing-the-best-printer-driver/ 9 | * Mapping PPD attributes (PageSize) to IPP attributes (media) 10 | * Command line tools 11 | * Filling in missing method implementations 12 | * Limiting number of concurrent jobs 13 | * Smart handling of job cancellation 14 | -------------------------------------------------------------------------------- /data/org.freedesktop.printerd.conf.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /printerd/pd-enumtypes.h.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | #ifndef __PD_ENUM_TYPES_H__ 3 | #define __PD_ENUM_TYPES_H__ 4 | 5 | #include 6 | 7 | G_BEGIN_DECLS 8 | /*** END file-header ***/ 9 | 10 | /*** BEGIN file-production ***/ 11 | 12 | /* enumerations from "@filename@" */ 13 | /*** END file-production ***/ 14 | 15 | /*** BEGIN value-header ***/ 16 | GType @enum_name@_get_type (void) G_GNUC_CONST; 17 | #define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) 18 | /*** END value-header ***/ 19 | 20 | /*** BEGIN file-tail ***/ 21 | G_END_DECLS 22 | 23 | #endif /* __PD_ENUM_TYPES_H__ */ 24 | /*** END file-tail ***/ 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: gcc 3 | before_install: 4 | - sudo apt-get update -qq 5 | - sudo apt-get install -qq gnome-common libglib2.0-dev gobject-introspection 6 | gtk-doc-tools libgudev-1.0-dev libpolkit-gobject-1-dev 7 | libpolkit-agent-1-dev dbus cups-filters libcups2-dev 8 | - "export DISPLAY=:99.0" 9 | - "sh -e /etc/init.d/xvfb start" 10 | script: ./autogen.sh --disable-systemd && 11 | DISPLAY=:99.0 make distcheck 12 | DISTCHECK_CONFIGURE_FLAGS="--disable-introspection --disable-systemd" 13 | TESTS_ENVIRONMENT='$(MAKE) -s printerd-session.pid;top_srcdir=$(top_srcdir) top_builddir=$(top_builddir) BOOKMARK=$(TEST_BOOKMARK) SESSION_LOG=$(TEST_SESSION_LOG)' 14 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = pd-view.py 2 | 3 | AM_CPPFLAGS = \ 4 | -I$(top_builddir) -I$(top_srcdir) \ 5 | -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ 6 | -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ 7 | -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ 8 | -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ 9 | -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ 10 | -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ 11 | -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ 12 | -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ 13 | -DPRINTERD_COMPILATION \ 14 | $(GLIB_CFLAGS) \ 15 | $(GIO_CFLAGS) \ 16 | $(WARN_CFLAGS) \ 17 | $(NULL) 18 | 19 | # ---------------------------------------------------------------------- 20 | 21 | bin_PROGRAMS = pd-cli 22 | 23 | pd_cli_SOURCES = \ 24 | pd-cli.c \ 25 | $(NULL) 26 | 27 | pd_cli_CFLAGS = \ 28 | -DG_LOG_DOMAIN=\"printerd\" \ 29 | $(NULL) 30 | 31 | pd_cli_LDADD = \ 32 | $(GLIB_LIBS) \ 33 | $(top_builddir)/src/libprinterddaemon.la \ 34 | $(NULL) 35 | 36 | 37 | 38 | -include $(top_srcdir)/git.mk 39 | -------------------------------------------------------------------------------- /tests/start-session-service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export top_builddir="${top_builddir-.}" 4 | if [ -x /usr/bin/dbus-run-session ]; then 5 | dbus-run-session -- bash <<"EOF" & 6 | printf "%s" "$DBUS_SESSION_BUS_ADDRESS" > \ 7 | "${top_builddir}"/printerd-session.bus 8 | printf "New D-Bus session bus at %s\n" "$DBUS_SESSION_BUS_ADDRESS" 9 | "${top_builddir}"/src/printerd --session -r -v \ 10 | &> "${top_builddir}"/printerd-session.log & 11 | jobs -p > "${top_builddir}"/printerd-session.pid 12 | printf "printerd started on session bus as PID %s\n" \ 13 | "$(cat "${top_builddir}"/printerd-session.pid)" 14 | wait 15 | EOF 16 | else 17 | "${top_builddir}"/src/printerd --session -r -v \ 18 | &> "${top_builddir}"/printerd-session.log & 19 | jobs -p > "${top_builddir}"/printerd-session.pid 20 | printf "printerd started on session bus as PID %s\n" \ 21 | "$(cat "${top_builddir}"/printerd-session.pid)" 22 | fi 23 | 24 | disown %- 25 | sleep 1 26 | kill -0 "$(cat "${top_builddir}"/printerd-session.pid)" 27 | RET="$?" 28 | if [ "${RET}" -ne 0 ]; then 29 | cat "${top_builddir}"/printerd-session.log 30 | exit "${RET}" 31 | fi 32 | exit 0 33 | -------------------------------------------------------------------------------- /printerd/pd-enumtypes.c.template: -------------------------------------------------------------------------------- 1 | /*** BEGIN file-header ***/ 2 | #include "pd-enums.h" 3 | #include "pd-enumtypes.h" 4 | 5 | /*** END file-header ***/ 6 | 7 | /*** BEGIN file-production ***/ 8 | /* enumerations from "@filename@" */ 9 | /*** END file-production ***/ 10 | 11 | /*** BEGIN value-header ***/ 12 | GType 13 | @enum_name@_get_type (void) 14 | { 15 | static volatile gsize g_define_type_id__volatile = 0; 16 | 17 | if (g_once_init_enter (&g_define_type_id__volatile)) 18 | { 19 | static const G@Type@Value values[] = { 20 | /*** END value-header ***/ 21 | 22 | /*** BEGIN value-production ***/ 23 | { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, 24 | /*** END value-production ***/ 25 | 26 | /*** BEGIN value-tail ***/ 27 | { 0, NULL, NULL } 28 | }; 29 | GType g_define_type_id = 30 | g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); 31 | g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); 32 | } 33 | 34 | return g_define_type_id__volatile; 35 | } 36 | 37 | /*** END value-tail ***/ 38 | 39 | /*** BEGIN file-tail ***/ 40 | /*** END file-tail ***/ 41 | -------------------------------------------------------------------------------- /printerd/pd-types.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General 16 | * Public License along with this library; if not, write to the 17 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 | * Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #if !defined (__PD_INSIDE_PRINTERD_H__) && !defined (PRINTERD_COMPILATION) 22 | #error "Only can be included directly." 23 | #endif 24 | 25 | #ifndef __PD_TYPES_H__ 26 | #define __PD_TYPES_H__ 27 | 28 | #include 29 | #include 30 | 31 | G_BEGIN_DECLS 32 | 33 | struct _PdClient; 34 | typedef struct _PdClient PdClient; 35 | 36 | G_END_DECLS 37 | 38 | #endif /* __PD_TYPES_H__ */ 39 | -------------------------------------------------------------------------------- /TESTS.md: -------------------------------------------------------------------------------- 1 | Running the tests 2 | ================= 3 | 4 | As printerd is built using automake, `make check` runs the tests. 5 | 6 | The way the tests are organised is that firstly, a new session D-Bus 7 | message bus is started and printerd is started for it. 8 | 9 | Next, the "started" and "Manager.GetPrinters" tests are run. These 10 | have to be run first of all. 11 | 12 | Once all the other tests have run, a special "stop-session-service" 13 | test runs which stops the running printerd and checks its logs for 14 | errors. 15 | 16 | These dependencies between tests are accounted for in `Makefile.am`, 17 | meaning that `make check -j` will do the right thing, running multiple 18 | tests concurrently against the session printerd service. 19 | 20 | Tips 21 | ---- 22 | 23 | Some tips for debugging problems found using the test suite: 24 | 25 | * To simply start printerd on its own session bus, you can use `make 26 | printerd-session.pid`. 27 | * To stop a printerd service started that way, you can run 28 | `make stop-session-service`. 29 | * To run all the tests without stopping the service at the end, run 30 | `make check STOP_TESTS=`. 31 | * To attach gdb to the running printerd, be aware that it was started 32 | using libtool and so you'll need to run `gdb src/.libs/lt-printerd 33 | $(cat printerd-session.pid)`. 34 | * You can run ippd against the session printerd service with `make 35 | run-ippd`. 36 | * Similarly, you can run pd-view against the session printerd service 37 | with `make run-pd-view`. 38 | -------------------------------------------------------------------------------- /src/pd-common.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012, 2014 Tim Waugh 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #ifndef __PD_COMMON_H__ 22 | #define __PD_COMMON_H__ 23 | 24 | #include "pd-daemontypes.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | GHashTable *pd_parse_ieee1284_id (const gchar *idstring); 29 | const gchar *pd_job_state_as_string (guint job_state); 30 | const gchar *pd_printer_state_as_string (guint printer_state); 31 | gchar *pd_get_unix_user (GDBusMethodInvocation *invocation); 32 | gchar ** add_or_remove_state_reason (const gchar *const *reasons, 33 | gchar add_or_remove, 34 | const gchar *reason); 35 | 36 | G_END_DECLS 37 | 38 | #endif /* __PD_COMMON_H__ */ 39 | -------------------------------------------------------------------------------- /printerd/printerd.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General 16 | * Public License along with this library; if not, write to the 17 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 | * Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #ifndef __PD_H__ 22 | #define __PD_H__ 23 | 24 | #if !defined(PRINTERD_API_IS_SUBJECT_TO_CHANGE) && !defined(PRINTERD_COMPILATION) 25 | #error libprinterd is unstable API. You must define PRINTERD_API_IS_SUBJECT_TO_CHANGE before including printerd/pd-.h 26 | #endif 27 | 28 | #define __PD_INSIDE_PRINTERD_H__ 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #undef __PD_INSIDE_PRINTERD_H__ 36 | 37 | #endif /* __PD_H__ */ 38 | -------------------------------------------------------------------------------- /src/pd-device-impl.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #ifndef __PD_DEVICE_IMPL_H__ 22 | #define __PD_DEVICE_IMPL_H__ 23 | 24 | #include "pd-daemontypes.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define PD_TYPE_DEVICE_IMPL (pd_device_impl_get_type ()) 29 | #define PD_DEVICE_IMPL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PD_TYPE_DEVICE_IMPL, PdDeviceImpl)) 30 | #define PD_IS_DEVICE_IMPL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PD_TYPE_DEVICE_IMPL)) 31 | 32 | GType pd_device_impl_get_type (void) G_GNUC_CONST; 33 | PdDaemon *pd_device_impl_get_daemon (PdDeviceImpl *device); 34 | const gchar *pd_device_impl_get_id (PdDeviceImpl *device); 35 | 36 | G_END_DECLS 37 | 38 | #endif /* __PD_DEVICE_IMPL_H__ */ 39 | -------------------------------------------------------------------------------- /src/pd-manager-impl.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #ifndef __PD_MANAGER_IMPL_H__ 22 | #define __PD_MANAGER_IMPL_H__ 23 | 24 | #include "pd-daemontypes.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define PD_TYPE_MANAGER_IMPL (pd_manager_impl_get_type ()) 29 | #define PD_MANAGER_IMPL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PD_TYPE_MANAGER_IMPL, PdManagerImpl)) 30 | #define PD_IS_MANAGER_IMPL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PD_TYPE_MANAGER_IMPL)) 31 | 32 | GType pd_manager_impl_get_type (void) G_GNUC_CONST; 33 | PdManager *pd_manager_impl_new (PdDaemon *daemon); 34 | PdDaemon *pd_manager_impl_get_daemon (PdManagerImpl *manager); 35 | 36 | G_END_DECLS 37 | 38 | #endif /* __PD_MANAGER_IMPL_H__ */ 39 | -------------------------------------------------------------------------------- /printerd/pd-error.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General 16 | * Public License along with this library; if not, write to the 17 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 | * Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #if !defined (__PD_INSIDE_PRINTERD_H__) && !defined (PRINTERD_COMPILATION) 22 | #error "Only can be included directly." 23 | #endif 24 | 25 | #ifndef __PD_ERROR_H__ 26 | #define __PD_ERROR_H__ 27 | 28 | #include 29 | 30 | G_BEGIN_DECLS 31 | 32 | /** 33 | * PD_ERROR: 34 | * 35 | * Error domain for printerd. Errors in this domain will be form the 36 | * #PdError enumeration. See #GError for more information on error 37 | * domains. 38 | */ 39 | #define PD_ERROR (pd_error_quark ()) 40 | 41 | GQuark pd_error_quark (void); 42 | 43 | G_END_DECLS 44 | 45 | #endif /* __PD_ERROR_H__ */ 46 | -------------------------------------------------------------------------------- /src/pd-job-impl.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Tim Waugh 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #ifndef __PD_JOB_IMPL_H__ 22 | #define __PD_JOB_IMPL_H__ 23 | 24 | #include "pd-daemontypes.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define PD_TYPE_JOB_IMPL (pd_job_impl_get_type ()) 29 | #define PD_JOB_IMPL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PD_TYPE_JOB_IMPL, PdJobImpl)) 30 | #define PD_IS_JOB_IMPL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PD_TYPE_JOB_IMPL)) 31 | 32 | GType pd_job_impl_get_type (void) G_GNUC_CONST; 33 | PdDaemon *pd_job_impl_get_daemon (PdJobImpl *job); 34 | void pd_job_impl_set_attribute (PdJobImpl *job, 35 | const gchar *name, 36 | GVariant *value); 37 | void pd_job_impl_start_sending (PdJobImpl *job); 38 | 39 | G_END_DECLS 40 | 41 | #endif /* __PD_JOB_IMPL_H__ */ 42 | -------------------------------------------------------------------------------- /src/pd-daemontypes.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #ifndef __PD_DAEMON_TYPES_H__ 22 | #define __PD_DAEMON_TYPES_H__ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | struct _PdDaemon; 32 | typedef struct _PdDaemon PdDaemon; 33 | 34 | struct _PdEngine; 35 | typedef struct _PdEngine PdEngine; 36 | 37 | struct _PdManagerImpl; 38 | typedef struct _PdManagerImpl PdManagerImpl; 39 | 40 | struct _PdDeviceImpl; 41 | typedef struct _PdDeviceImpl PdDeviceImpl; 42 | 43 | struct _PdPrinterImpl; 44 | typedef struct _PdPrinterImpl PdPrinterImpl; 45 | 46 | struct _PdJobImpl; 47 | typedef struct _PdJobImpl PdJobImpl; 48 | 49 | #endif /* __PD_DAEMON_TYPES_H__ */ 50 | -------------------------------------------------------------------------------- /tests/python1/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | OUTPUT="$(mktemp /tmp/printerd-XXXXXXXXXX)" 6 | function finish { 7 | rm -f "$OUTPUT" 8 | } 9 | trap finish EXIT 10 | 11 | # Create a printer. 12 | printf "CreatePrinter\n" 13 | result=$(gdbus call --session \ 14 | --dest $PD_DEST \ 15 | --object-path $PD_PATH/Manager \ 16 | --method $PD_IFACE.Manager.CreatePrinter \ 17 | "{}" \ 18 | "python1" \ 19 | "printer description" \ 20 | "printer location" \ 21 | '["ipp://remote:631/printers/remote"]' \ 22 | "{}") 23 | 24 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 25 | if [ -z "$objpath" ]; then 26 | printf "Expected (objectpath): %s\n" "$result" 27 | result_is 1 28 | fi 29 | 30 | # Now try to examine it using Python 31 | PD_USE_SESSION_BUS=1 \ 32 | LD_LIBRARY_PATH=${top_builddir}/printerd/.libs:$LD_LIBRARY_PATH \ 33 | GI_TYPELIB_PATH=${top_builddir}/printerd \ 34 | ${PYTHON} "$(dirname $0)"/Manager.GetPrinters.py > "$OUTPUT" 35 | cat "$OUTPUT" 36 | RETVAL=$? 37 | if [ "$RETVAL" -ne 0 ]; then 38 | result_is $RETVAL 39 | fi 40 | 41 | if ! grep -q "$objpath" "$OUTPUT"; then 42 | printf "%s not in GetPrinters result\n" "$objpath" 43 | result_is 1 44 | fi 45 | 46 | # Delete the printer again 47 | printf "DeletePrinter\n" 48 | result=$(gdbus call --session \ 49 | --dest $PD_DEST \ 50 | --object-path $PD_PATH/Manager \ 51 | --method $PD_IFACE.Manager.DeletePrinter \ 52 | "{}" \ 53 | "$objpath") 54 | 55 | if [ "$result" != "()" ]; then 56 | printf "Expected (): %s\n" "$result" 57 | result_is 1 58 | fi 59 | 60 | result_is 0 61 | -------------------------------------------------------------------------------- /tests/Manager.GetPrinters/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Create two printers 6 | declare -A objpath 7 | for name in printer1 printer2; do 8 | printf "CreatePrinter %s\n" "$name" 9 | result=$(gdbus call --session \ 10 | --dest $PD_DEST \ 11 | --object-path $PD_PATH/Manager \ 12 | --method $PD_IFACE.Manager.CreatePrinter \ 13 | "{}" \ 14 | "$name" \ 15 | "printer description" \ 16 | "printer location" \ 17 | '["ipp://remote:631/printers/remote"]' \ 18 | "{}") 19 | 20 | objpath[$name]=$(printf "%s" "$result" | \ 21 | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 22 | if [ -z "${objpath[$name]}" ]; then 23 | printf "Expected (objectpath): %s\n" "$result" 24 | result_is 1 25 | fi 26 | done 27 | 28 | # Now check the Manager tells us about them 29 | printf "GetPrinters\n" 30 | if ! diff -u - <(gdbus call --session \ 31 | --dest $PD_DEST \ 32 | --object-path $PD_PATH/Manager \ 33 | --method $PD_IFACE.Manager.GetPrinters | \ 34 | sed -e 's:^(\[objectpath ::' -e 's:\],)$::' \ 35 | -e "s:', ':'\n':g" | \ 36 | LC_ALL=C sort) < $@ 7 | 8 | dbusconfdir = $(sysconfdir)/dbus-1/system.d 9 | dbusconf_in_files = org.freedesktop.printerd.conf.in 10 | dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf) 11 | 12 | $(dbusconf_DATA): $(dbusconf_in_files) Makefile 13 | cp $< $@ 14 | 15 | systemdservice_in_files = printerd.service.in ippd.service.in 16 | systemdservice_generated_files = $(systemdservice_in_files:.service.in=.service) 17 | systemdsocket_files = ippd.socket 18 | 19 | if HAVE_SYSTEMD 20 | systemdservicedir = $(DESTDIR)$(systemdsystemunitdir) 21 | systemdservice_DATA = \ 22 | $(systemdservice_generated_files) \ 23 | $(systemdsocket_files) 24 | 25 | %.service: %.service.in Makefile 26 | @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ 27 | endif 28 | 29 | polkitdir = $(datadir)/polkit-1/actions 30 | polkit_in_files = org.freedesktop.printerd.policy.in 31 | polkit_DATA = $(polkit_in_files:.policy.in=.policy) 32 | 33 | @INTLTOOL_POLICY_RULE@ 34 | 35 | EXTRA_DIST = \ 36 | org.freedesktop.printerd.xml \ 37 | $(systemdservice_in_files) \ 38 | $(systemdsocket_files) \ 39 | $(dbusservice_in_files) \ 40 | $(dbusconf_in_files) \ 41 | $(polkit_in_files) \ 42 | $(NULL) 43 | 44 | DISTCLEANFILES = \ 45 | $(dbusservice_DATA) \ 46 | $(dbusconf_DATA) \ 47 | $(polkit_DATA) \ 48 | $(systemdservice_generated_files) 49 | 50 | clean-local : 51 | rm -f *~ $(dbusservice_DATA) $(dbusconf_DATA) $(systemdservice_generated_files) $(polkit_DATA) 52 | 53 | -include $(top_srcdir)/git.mk 54 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:21 2 | MAINTAINER Tim Waugh 3 | 4 | # Apply updates 5 | RUN yum -y update; yum clean all 6 | 7 | # Perform the following steps all in one go, in order to avoid 8 | # inflating the image size: 9 | # - Install dnf so clean-up is easier 10 | # - Install build tools 11 | # - Install build dependencies 12 | # - Install printerd runtime dependencies (for test-suite) 13 | # - Build and install 14 | # - Remove build tools and dependencies 15 | RUN yum -y install dnf && \ 16 | dnf -y install git automake autoconf intltool gtk-doc gnome-common make && \ 17 | dnf -y install glib2-devel gobject-introspection-devel libgudev1-devel \ 18 | polkit-devel cups-devel systemd-devel && \ 19 | dnf -y install cups cups-filters && \ 20 | mkdir /printerd && \ 21 | cd /printerd && \ 22 | git clone git://github.com/hughsie/printerd.git && \ 23 | cd printerd && \ 24 | ./autogen.sh --prefix=/usr && \ 25 | make && \ 26 | (make check || (cat test-suite.log; exit 1)) && \ 27 | make install && \ 28 | dnf -y remove glib2-devel gobject-introspection-devel libgudev1-devel \ 29 | polkit-devel cups-devel systemd-devel && \ 30 | dnf -y remove git automake autoconf intltool gtk-doc gnome-common make && \ 31 | dnf clean all && \ 32 | yum -y remove dnf && \ 33 | yum clean all && \ 34 | rm -rf /printerd/printerd 35 | 36 | # Install printerd runtime dependencies 37 | RUN yum -y install libgudev1 polkit cups systemd-libs; \ 38 | yum clean all 39 | 40 | # Install ippd runtime dependencies 41 | RUN yum -y install python3 python3-gobject; \ 42 | yum clean all 43 | RUN yum -y install --enablerepo=updates-testing python3-cups; \ 44 | yum clean all 45 | 46 | # Prepare to start everything up 47 | RUN mkdir -p /var/run/dbus 48 | ADD docker/run-printerd.sh /printerd/run-printerd.sh 49 | RUN chmod +x /printerd/run-printerd.sh 50 | CMD [ "/printerd/run-printerd.sh" ] 51 | -------------------------------------------------------------------------------- /tests/createprinter2/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Create a printer. 6 | printf "CreatePrinter\n" 7 | result=$(gdbus call --session \ 8 | --dest $PD_DEST \ 9 | --object-path $PD_PATH/Manager \ 10 | --method $PD_IFACE.Manager.CreatePrinter \ 11 | "{}" \ 12 | "create-printer2" \ 13 | "printer description" \ 14 | "printer location" \ 15 | '["ipp://remote:631/printers/remote"]' \ 16 | "{}") 17 | 18 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 19 | if [ -z "$objpath" ]; then 20 | printf "Expected (objectpath): %s\n" "$result" 21 | result_is 1 22 | fi 23 | 24 | # Now call SetDeviceUris 25 | printf "SetDeviceUris\n" 26 | result=$(gdbus call --session \ 27 | --dest $PD_DEST \ 28 | --object-path "$objpath" \ 29 | --method $PD_IFACE.Printer.SetDeviceUris \ 30 | '["ipp://remote1:631/dest1","ipp://remote2:631/dest2"]') 31 | 32 | if [ "$result" != "()" ]; then 33 | printf "Expected (): %s\n" "$result" 34 | result_is 1 35 | fi 36 | 37 | # Verify it worked. 38 | printf "Examining %s\n" "$objpath" 39 | if ! diff -u - <(gdbus introspect --session --only-properties \ 40 | --dest $PD_DEST \ 41 | --object-path "$objpath" | \ 42 | grep ' DeviceUris = ' | \ 43 | sed -e 's,^ *readonly ,,') << "EOF" 44 | as DeviceUris = ['ipp://remote1:631/dest1', 'ipp://remote2:631/dest2']; 45 | EOF 46 | then 47 | printf "DeviceUris property differs from expected\n" 48 | result_is 1 49 | fi 50 | 51 | # Now delete it. 52 | printf "DeletePrinter\n" 53 | result=$(gdbus call --session \ 54 | --dest $PD_DEST \ 55 | --object-path $PD_PATH/Manager \ 56 | --method $PD_IFACE.Manager.DeletePrinter \ 57 | "{}" \ 58 | "$objpath") 59 | 60 | if [ "$result" != "()" ]; then 61 | printf "Expected (): %s\n" "$result" 62 | result_is 1 63 | fi 64 | 65 | result_is 0 66 | -------------------------------------------------------------------------------- /tests/updatedriver1/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | PPD="$(simple_ppd)" 6 | function finish { 7 | rm -f "${PPD}" 8 | } 9 | trap finish EXIT 10 | 11 | # Create a printer. 12 | printf "CreatePrinter\n" 13 | result=$(gdbus call --session \ 14 | --dest $PD_DEST \ 15 | --object-path $PD_PATH/Manager \ 16 | --method $PD_IFACE.Manager.CreatePrinter \ 17 | "{}" \ 18 | "updatedriver1" \ 19 | "printer description" \ 20 | "printer location" \ 21 | '["ipp://remote:631/printers/remote"]' \ 22 | "{}") 23 | 24 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 25 | if [ -z "$objpath" ]; then 26 | printf "Expected (objectpath): %s\n" "$result" 27 | result_is 1 28 | fi 29 | 30 | # Update the driver with a specified driver-name 31 | printf "UpdateDriver with driver-name\n" 32 | result=$(gdbus call --session \ 33 | --dest $PD_DEST \ 34 | --object-path "$objpath" \ 35 | --method $PD_IFACE.Printer.UpdateDriver \ 36 | "{'driver-name':<'${PPD}'>}") 37 | if [ "$result" != "()" ]; then 38 | printf "Expected (): %s\n" "$result" 39 | result_is 1 40 | fi 41 | 42 | # Verify the Driver property. 43 | printf "Examining %s\n" "$objpath" 44 | if ! diff -u - <(gdbus introspect --session --only-properties \ 45 | --dest $PD_DEST \ 46 | --object-path "$objpath" | \ 47 | grep 's Driver = ' | LC_ALL=C sort | \ 48 | sed -e 's,^ *readonly ,,') < 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #ifndef __PD_DAEMON_H__ 22 | #define __PD_DAEMON_H__ 23 | 24 | #include "pd-daemontypes.h" 25 | 26 | G_BEGIN_DECLS 27 | 28 | #define PD_TYPE_DAEMON (pd_daemon_get_type ()) 29 | #define PD_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PD_TYPE_DAEMON, PdDaemon)) 30 | #define PD_IS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PD_TYPE_DAEMON)) 31 | 32 | GType pd_daemon_get_type (void) G_GNUC_CONST; 33 | PdDaemon *pd_daemon_new (GDBusConnection *connection, 34 | gboolean is_session); 35 | GDBusConnection *pd_daemon_get_connection (PdDaemon *daemon); 36 | GDBusObjectManagerServer *pd_daemon_get_object_manager (PdDaemon *daemon); 37 | PolkitAuthority *pd_daemon_get_authority (PdDaemon *daemon); 38 | PdObject *pd_daemon_find_object (PdDaemon *daemon, 39 | const gchar *object_path); 40 | PdEngine *pd_daemon_get_engine (PdDaemon *daemon); 41 | gboolean pd_daemon_check_authorization_sync (PdDaemon *daemon, 42 | GVariant *options, 43 | const gchar *description, 44 | GDBusMethodInvocation *invocation, 45 | const gchar *action_id, 46 | ...); 47 | 48 | G_END_DECLS 49 | 50 | #endif /* __PD_DAEMON_H__ */ 51 | -------------------------------------------------------------------------------- /tests/createprinter5/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | PPD="$(simple_ppd)" 6 | function finish { 7 | rm -f "${PPD}" 8 | } 9 | trap finish EXIT 10 | 11 | # Create a printer. 12 | printf "CreatePrinter\n" 13 | result=$(gdbus call --session \ 14 | --dest $PD_DEST \ 15 | --object-path $PD_PATH/Manager \ 16 | --method $PD_IFACE.Manager.CreatePrinter \ 17 | "{'driver-name':<'${PPD}'>}" \ 18 | "create-printer5" \ 19 | "printer description" \ 20 | "printer location" \ 21 | '["ipp://remote:631/printers/remote"]' \ 22 | "{}") 23 | 24 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 25 | if [ -z "$objpath" ]; then 26 | printf "Expected (objectpath): %s\n" "$result" 27 | result_is 1 28 | fi 29 | 30 | # Verify the Driver property. 31 | printf "Examining %s\n" "$objpath" 32 | if ! diff -u - <(gdbus introspect --session --only-properties \ 33 | --dest $PD_DEST \ 34 | --object-path "$objpath" | \ 35 | grep ' = ' | LC_ALL=C sort | \ 36 | sed \ 37 | -e 's,^ *readonly ,,' \ 38 | -e '/^b IsDefault /d' \ 39 | -e '/^ao ActiveJobs /d' \ 40 | -e '/^as DeviceUris /d' \ 41 | -e '/as StateReasons /d' \ 42 | -e '/a{sv} Defaults /d' \ 43 | -e '/a{sv} Supported /d' \ 44 | -e '/b IsAcceptingJobs /d' \ 45 | -e '/b IsShared /d' \ 46 | -e '/s Description /d' \ 47 | -e '/s Ieee1284Id /d' \ 48 | -e '/s Location /d' \ 49 | -e '/s Name /d' \ 50 | -e '/u State /d') < 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General 16 | * Public License along with this library; if not, write to the 17 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 | * Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #include "config.h" 22 | #include 23 | 24 | #include "pd-error.h" 25 | 26 | /** 27 | * SECTION:pderror 28 | * @title: PdError 29 | * @short_description: Possible errors that can be returned 30 | * 31 | * Error codes and D-Bus errors. 32 | */ 33 | 34 | static const GDBusErrorEntry dbus_error_entries[] = 35 | { 36 | {PD_ERROR_FAILED, "org.freedesktop.printerd.Error.Failed"}, 37 | {PD_ERROR_CANCELLED, "org.freedesktop.printerd.Error.Cancelled"}, 38 | {PD_ERROR_UNIMPLEMENTED, "org.freedesktop.printerd.Error.Unimplemented"}, 39 | {PD_ERROR_UNSUPPORTED_DOCUMENT_TYPE, "org.freedesktop.printerd.Error.UnsupportedDocumentType"}, 40 | }; 41 | 42 | GQuark 43 | pd_error_quark (void) 44 | { 45 | G_STATIC_ASSERT (G_N_ELEMENTS (dbus_error_entries) == PD_ERROR_NUM_ENTRIES); 46 | static volatile gsize quark_volatile = 0; 47 | g_dbus_error_register_error_domain ("pd-error-quark", 48 | &quark_volatile, 49 | dbus_error_entries, 50 | G_N_ELEMENTS (dbus_error_entries)); 51 | return (GQuark) quark_volatile; 52 | } 53 | -------------------------------------------------------------------------------- /po/en_GB.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Tim Waugh , 2009. 6 | # Richard Hughes , 2011. 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2011-07-20 11:44+0000\n" 13 | "Last-Translator: hughsie \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: en_GB\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 | 21 | #: ../data/org.freedesktop.printerd.policy.in.h:1 22 | msgid "Add a printer" 23 | msgstr "" 24 | 25 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 26 | #: ../src/pd-manager-impl.c:300 27 | msgid "Authentication is required to add a printer" 28 | msgstr "" 29 | 30 | #: ../data/org.freedesktop.printerd.policy.in.h:3 31 | msgid "Add a job" 32 | msgstr "" 33 | 34 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 35 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 36 | msgid "Authentication is required to add a job" 37 | msgstr "" 38 | 39 | #: ../data/org.freedesktop.printerd.policy.in.h:5 40 | msgid "Cancel a job" 41 | msgstr "" 42 | 43 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 44 | msgid "Authentication is required to cancel a job" 45 | msgstr "" 46 | 47 | #: ../src/main.c:119 ../tools/pd-cli.c:503 48 | msgid "Show extra debugging information" 49 | msgstr "" 50 | 51 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 52 | #: ../src/pd-job-impl.c:1481 53 | msgid "Not job owner" 54 | msgstr "" 55 | 56 | #: ../src/pd-job-impl.c:1279 57 | msgid "No more documents allowed" 58 | msgstr "" 59 | 60 | #: ../src/pd-job-impl.c:1289 61 | msgid "Bad AddDocumentCall" 62 | msgstr "" 63 | 64 | #: ../src/pd-job-impl.c:1521 65 | msgid "Already canceled" 66 | msgstr "" 67 | 68 | #: ../src/pd-job-impl.c:1579 69 | msgid "Cannot cancel completed job" 70 | msgstr "" 71 | 72 | #: ../src/pd-manager-impl.c:337 73 | msgid "Not found" 74 | msgstr "" 75 | -------------------------------------------------------------------------------- /printerd/pd-client.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General 16 | * Public License along with this library; if not, write to the 17 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 | * Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | #if !defined (__PD_INSIDE_PRINTERD_H__) && !defined (PRINTERD_COMPILATION) 22 | #error "Only can be included directly." 23 | #endif 24 | 25 | #ifndef __PD_CLIENT_H__ 26 | #define __PD_CLIENT_H__ 27 | 28 | #include 29 | #include 30 | 31 | G_BEGIN_DECLS 32 | 33 | #define PD_TYPE_CLIENT (pd_client_get_type ()) 34 | #define PD_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PD_TYPE_CLIENT, PdClient)) 35 | #define PD_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PD_TYPE_CLIENT)) 36 | 37 | GType pd_client_get_type (void) G_GNUC_CONST; 38 | void pd_client_new (GCancellable *cancellable, 39 | GAsyncReadyCallback callback, 40 | gpointer user_data); 41 | PdClient *pd_client_new_finish (GAsyncResult *res, 42 | GError **error); 43 | PdClient *pd_client_new_sync (GCancellable *cancellable, 44 | GError **error); 45 | GDBusObjectManager *pd_client_get_object_manager (PdClient *client); 46 | PdManager *pd_client_get_manager (PdClient *client); 47 | void pd_client_settle (PdClient *client); 48 | 49 | PdObject *pd_client_get_object (PdClient *client, 50 | const gchar *object_path); 51 | PdObject *pd_client_peek_object (PdClient *client, 52 | const gchar *object_path); 53 | 54 | G_END_DECLS 55 | 56 | #endif /* __PD_CLIENT_H__ */ 57 | -------------------------------------------------------------------------------- /data/org.freedesktop.printerd.policy.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | The printerd Project 9 | http://printerd.freedesktop.org/ 10 | printer 11 | 12 | 13 | 14 | <_description>Add, modify, or delete a printer 15 | <_message>Authentication is required to modify printers 16 | 17 | auth_admin 18 | auth_admin 19 | yes 20 | 21 | 22 | 23 | 24 | <_description>Add a printer 25 | <_message>Authentication is required to add a printer 26 | 27 | auth_admin 28 | auth_admin 29 | yes 30 | 31 | 32 | 33 | 34 | <_description>Modify a printer 35 | <_message>Authentication is required to modify a printer 36 | 37 | auth_admin 38 | auth_admin 39 | yes 40 | 41 | 42 | 43 | 44 | <_description>Add a job 45 | <_message>Authentication is required to add a job 46 | 47 | yes 48 | yes 49 | yes 50 | 51 | 52 | 53 | 54 | 55 | <_description>Cancel a job 56 | <_message>Authentication is required to cancel a job 57 | 58 | yes 59 | yes 60 | yes 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /po/en_US.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: printerd\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 11 | "PO-Revision-Date: 2012-05-30 15:58+0000\n" 12 | "Last-Translator: FULL NAME \n" 13 | "Language-Team: English (United States) (http://www.transifex.com/projects/p/" 14 | "printerd/language/en_US/)\n" 15 | "Language: en_US\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 20 | 21 | #: ../data/org.freedesktop.printerd.policy.in.h:1 22 | msgid "Add a printer" 23 | msgstr "Add a printer" 24 | 25 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 26 | #: ../src/pd-manager-impl.c:300 27 | msgid "Authentication is required to add a printer" 28 | msgstr "Authentication is required to add a printer" 29 | 30 | #: ../data/org.freedesktop.printerd.policy.in.h:3 31 | msgid "Add a job" 32 | msgstr "Add a job" 33 | 34 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 35 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 36 | msgid "Authentication is required to add a job" 37 | msgstr "Authentication is required to add a job" 38 | 39 | #: ../data/org.freedesktop.printerd.policy.in.h:5 40 | msgid "Cancel a job" 41 | msgstr "Cancel a job" 42 | 43 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 44 | msgid "Authentication is required to cancel a job" 45 | msgstr "Authentication is required to cancel a job" 46 | 47 | #: ../src/main.c:119 ../tools/pd-cli.c:503 48 | msgid "Show extra debugging information" 49 | msgstr "Show extra debugging information" 50 | 51 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 52 | #: ../src/pd-job-impl.c:1481 53 | msgid "Not job owner" 54 | msgstr "" 55 | 56 | #: ../src/pd-job-impl.c:1279 57 | msgid "No more documents allowed" 58 | msgstr "" 59 | 60 | #: ../src/pd-job-impl.c:1289 61 | msgid "Bad AddDocumentCall" 62 | msgstr "" 63 | 64 | #: ../src/pd-job-impl.c:1521 65 | msgid "Already canceled" 66 | msgstr "" 67 | 68 | #: ../src/pd-job-impl.c:1579 69 | msgid "Cannot cancel completed job" 70 | msgstr "" 71 | 72 | #: ../src/pd-manager-impl.c:337 73 | msgid "Not found" 74 | msgstr "Not found" 75 | -------------------------------------------------------------------------------- /po/vi.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # Anh Phan , 2013 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2013-11-20 10:22+0000\n" 13 | "Last-Translator: Anh Phan \n" 14 | "Language-Team: Vietnamese (http://www.transifex.com/projects/p/printerd/" 15 | "language/vi/)\n" 16 | "Language: vi\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=1; plural=0;\n" 21 | 22 | #: ../data/org.freedesktop.printerd.policy.in.h:1 23 | msgid "Add a printer" 24 | msgstr "Thêm vào máy in" 25 | 26 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 27 | #: ../src/pd-manager-impl.c:300 28 | msgid "Authentication is required to add a printer" 29 | msgstr "Cần xác nhận việc thêm vào máy in" 30 | 31 | #: ../data/org.freedesktop.printerd.policy.in.h:3 32 | msgid "Add a job" 33 | msgstr "Thêm tác vụ" 34 | 35 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 36 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 37 | msgid "Authentication is required to add a job" 38 | msgstr "Cần xác nhận để thêm tác vụ" 39 | 40 | #: ../data/org.freedesktop.printerd.policy.in.h:5 41 | msgid "Cancel a job" 42 | msgstr "Hủy bỏ tác vụ" 43 | 44 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 45 | msgid "Authentication is required to cancel a job" 46 | msgstr "Yêu cầu xác nhận để hủy bỏ tác vụ" 47 | 48 | #: ../src/main.c:119 ../tools/pd-cli.c:503 49 | msgid "Show extra debugging information" 50 | msgstr "Hiển thị các thông tin về lỗi" 51 | 52 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 53 | #: ../src/pd-job-impl.c:1481 54 | msgid "Not job owner" 55 | msgstr "" 56 | 57 | #: ../src/pd-job-impl.c:1279 58 | msgid "No more documents allowed" 59 | msgstr "" 60 | 61 | #: ../src/pd-job-impl.c:1289 62 | msgid "Bad AddDocumentCall" 63 | msgstr "" 64 | 65 | #: ../src/pd-job-impl.c:1521 66 | msgid "Already canceled" 67 | msgstr "" 68 | 69 | #: ../src/pd-job-impl.c:1579 70 | msgid "Cannot cancel completed job" 71 | msgstr "" 72 | 73 | #: ../src/pd-manager-impl.c:337 74 | msgid "Not found" 75 | msgstr "Không tìm thấy" 76 | -------------------------------------------------------------------------------- /po/es.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # strel, 2013 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2013-11-20 10:22+0000\n" 13 | "Last-Translator: strel\n" 14 | "Language-Team: Spanish (http://www.transifex.com/projects/p/printerd/" 15 | "language/es/)\n" 16 | "Language: es\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 21 | 22 | #: ../data/org.freedesktop.printerd.policy.in.h:1 23 | msgid "Add a printer" 24 | msgstr "Añadir una impresora" 25 | 26 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 27 | #: ../src/pd-manager-impl.c:300 28 | msgid "Authentication is required to add a printer" 29 | msgstr "Se requiere identificación para añadir una impresora" 30 | 31 | #: ../data/org.freedesktop.printerd.policy.in.h:3 32 | msgid "Add a job" 33 | msgstr "Añadir una tarea" 34 | 35 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 36 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 37 | msgid "Authentication is required to add a job" 38 | msgstr "Se requiere identificación para añadir una tarea" 39 | 40 | #: ../data/org.freedesktop.printerd.policy.in.h:5 41 | msgid "Cancel a job" 42 | msgstr "Cancelar una tarea" 43 | 44 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 45 | msgid "Authentication is required to cancel a job" 46 | msgstr "Se requiere identificación para cancelar una tarea" 47 | 48 | #: ../src/main.c:119 ../tools/pd-cli.c:503 49 | msgid "Show extra debugging information" 50 | msgstr "Mostrar información extra de depuración (debug)" 51 | 52 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 53 | #: ../src/pd-job-impl.c:1481 54 | msgid "Not job owner" 55 | msgstr "" 56 | 57 | #: ../src/pd-job-impl.c:1279 58 | msgid "No more documents allowed" 59 | msgstr "" 60 | 61 | #: ../src/pd-job-impl.c:1289 62 | msgid "Bad AddDocumentCall" 63 | msgstr "" 64 | 65 | #: ../src/pd-job-impl.c:1521 66 | msgid "Already canceled" 67 | msgstr "" 68 | 69 | #: ../src/pd-job-impl.c:1579 70 | msgid "Cannot cancel completed job" 71 | msgstr "" 72 | 73 | #: ../src/pd-manager-impl.c:337 74 | msgid "Not found" 75 | msgstr "No encontrado" 76 | -------------------------------------------------------------------------------- /po/tr.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # Batuhan Büyükgüzel , 2012 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2013-11-20 10:22+0000\n" 13 | "Last-Translator: Batuhan Büyükgüzel \n" 14 | "Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/" 15 | "printerd/language/tr_TR/)\n" 16 | "Language: tr_TR\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=1; plural=0;\n" 21 | 22 | #: ../data/org.freedesktop.printerd.policy.in.h:1 23 | msgid "Add a printer" 24 | msgstr "Yazıcı ekle" 25 | 26 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 27 | #: ../src/pd-manager-impl.c:300 28 | msgid "Authentication is required to add a printer" 29 | msgstr "Yazıcı eklemek için doğrulama gerekli" 30 | 31 | #: ../data/org.freedesktop.printerd.policy.in.h:3 32 | msgid "Add a job" 33 | msgstr "Görev ekle" 34 | 35 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 36 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 37 | msgid "Authentication is required to add a job" 38 | msgstr "Görev eklemek için doğrulama gerekli" 39 | 40 | #: ../data/org.freedesktop.printerd.policy.in.h:5 41 | msgid "Cancel a job" 42 | msgstr "Görevi iptal et" 43 | 44 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 45 | msgid "Authentication is required to cancel a job" 46 | msgstr "Görevi iptal etmek için doğrulama gerekli" 47 | 48 | #: ../src/main.c:119 ../tools/pd-cli.c:503 49 | msgid "Show extra debugging information" 50 | msgstr "Ek olarak hata ayıklama bilgisini göster" 51 | 52 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 53 | #: ../src/pd-job-impl.c:1481 54 | msgid "Not job owner" 55 | msgstr "" 56 | 57 | #: ../src/pd-job-impl.c:1279 58 | msgid "No more documents allowed" 59 | msgstr "" 60 | 61 | #: ../src/pd-job-impl.c:1289 62 | msgid "Bad AddDocumentCall" 63 | msgstr "" 64 | 65 | #: ../src/pd-job-impl.c:1521 66 | msgid "Already canceled" 67 | msgstr "" 68 | 69 | #: ../src/pd-job-impl.c:1579 70 | msgid "Cannot cancel completed job" 71 | msgstr "" 72 | 73 | #: ../src/pd-manager-impl.c:337 74 | msgid "Not found" 75 | msgstr "Bulunamadı" 76 | -------------------------------------------------------------------------------- /po/id.po: -------------------------------------------------------------------------------- 1 | # Translation of printerd into Indonesian 2 | # Copyright (C) 2012 THE printerd'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the printerd package. 4 | # Andika Triwidada , 2012. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: printerd master\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 11 | "PO-Revision-Date: 2012-05-22 20:54+0700\n" 12 | "Last-Translator: Andika Triwidada \n" 13 | "Language-Team: Indonesia \n" 14 | "Language: \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=utf-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=1; plural=0;\n" 19 | "X-Poedit-Language: Indonesian\n" 20 | "X-Poedit-Country: INDONESIA\n" 21 | "X-Poedit-SourceCharset: utf-8\n" 22 | 23 | #: ../data/org.freedesktop.printerd.policy.in.h:1 24 | msgid "Add a printer" 25 | msgstr "Tambah pencetak" 26 | 27 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 28 | #: ../src/pd-manager-impl.c:300 29 | msgid "Authentication is required to add a printer" 30 | msgstr "Otentikasi diperlukan untuk menambah pencetak" 31 | 32 | #: ../data/org.freedesktop.printerd.policy.in.h:3 33 | msgid "Add a job" 34 | msgstr "Tambah tugas" 35 | 36 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 37 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 38 | msgid "Authentication is required to add a job" 39 | msgstr "Otentikasi diperlukan untuk menambah tugas" 40 | 41 | #: ../data/org.freedesktop.printerd.policy.in.h:5 42 | msgid "Cancel a job" 43 | msgstr "Batalkan tugas" 44 | 45 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 46 | msgid "Authentication is required to cancel a job" 47 | msgstr "Otentikasi diperlukan untuk membatalkan tugas" 48 | 49 | #: ../src/main.c:119 ../tools/pd-cli.c:503 50 | msgid "Show extra debugging information" 51 | msgstr "Tampilkan informasi pengawakutuan ekstra" 52 | 53 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 54 | #: ../src/pd-job-impl.c:1481 55 | msgid "Not job owner" 56 | msgstr "" 57 | 58 | #: ../src/pd-job-impl.c:1279 59 | msgid "No more documents allowed" 60 | msgstr "" 61 | 62 | #: ../src/pd-job-impl.c:1289 63 | msgid "Bad AddDocumentCall" 64 | msgstr "" 65 | 66 | #: ../src/pd-job-impl.c:1521 67 | msgid "Already canceled" 68 | msgstr "" 69 | 70 | #: ../src/pd-job-impl.c:1579 71 | msgid "Cannot cancel completed job" 72 | msgstr "" 73 | 74 | #: ../src/pd-manager-impl.c:337 75 | msgid "Not found" 76 | msgstr "Tak ditemukan" 77 | -------------------------------------------------------------------------------- /src/pd-printer-impl.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * Copyright (C) 2014 Tim Waugh 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | * 20 | */ 21 | 22 | #ifndef __PD_PRINTER_IMPL_H__ 23 | #define __PD_PRINTER_IMPL_H__ 24 | 25 | #include "pd-daemontypes.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define PD_TYPE_PRINTER_IMPL (pd_printer_impl_get_type ()) 30 | #define PD_PRINTER_IMPL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PD_TYPE_PRINTER_IMPL, PdPrinterImpl)) 31 | #define PD_IS_PRINTER_IMPL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PD_TYPE_PRINTER_IMPL)) 32 | 33 | /* File descriptors for filters and backends */ 34 | #define PD_FD_BACK 3 35 | #define PD_FD_SIDE 4 36 | #define PD_FD_MAX 5 37 | 38 | GType pd_printer_impl_get_type (void) G_GNUC_CONST; 39 | PdDaemon *pd_printer_impl_get_daemon (PdPrinterImpl *printer); 40 | const gchar *pd_printer_impl_get_id (PdPrinterImpl *printer); 41 | void pd_printer_impl_set_id (PdPrinterImpl *printer, 42 | const gchar *id); 43 | void pd_printer_impl_do_update_defaults (PdPrinterImpl *printer, 44 | GVariant *defaults); 45 | void pd_printer_impl_add_state_reason (PdPrinterImpl *printer, 46 | const gchar *reason); 47 | void pd_printer_impl_remove_state_reason (PdPrinterImpl *printer, 48 | const gchar *reason); 49 | const gchar *pd_printer_impl_get_uri (PdPrinterImpl *printer); 50 | PdJob *pd_printer_impl_get_next_job (PdPrinterImpl *printer); 51 | gboolean pd_printer_impl_set_driver (PdPrinterImpl *printer, 52 | const gchar *driver); 53 | gboolean pd_printer_impl_dup_final_content_type (PdPrinterImpl *printer, 54 | gchar **content_type, 55 | gchar **filter, 56 | GError **error); 57 | 58 | G_END_DECLS 59 | 60 | #endif /* __PD_PRINTER_IMPL_H__ */ 61 | -------------------------------------------------------------------------------- /po/pt_BR.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # Rafael Ferreira , 2012 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2013-11-20 10:22+0000\n" 13 | "Last-Translator: Rafael Ferreira \n" 14 | "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/" 15 | "printerd/language/pt_BR/)\n" 16 | "Language: pt_BR\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 21 | 22 | #: ../data/org.freedesktop.printerd.policy.in.h:1 23 | msgid "Add a printer" 24 | msgstr "Adicionar uma impressora" 25 | 26 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 27 | #: ../src/pd-manager-impl.c:300 28 | msgid "Authentication is required to add a printer" 29 | msgstr "Autenticação é necessária para adicionar uma impressora" 30 | 31 | #: ../data/org.freedesktop.printerd.policy.in.h:3 32 | msgid "Add a job" 33 | msgstr "Adicionar um trabalho" 34 | 35 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 36 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 37 | msgid "Authentication is required to add a job" 38 | msgstr "Autenticação é necessária para adicionar um trabalho" 39 | 40 | #: ../data/org.freedesktop.printerd.policy.in.h:5 41 | msgid "Cancel a job" 42 | msgstr "Cancelar um trabalho" 43 | 44 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 45 | msgid "Authentication is required to cancel a job" 46 | msgstr "Autenticação é necessária para cancelar um trabalho" 47 | 48 | #: ../src/main.c:119 ../tools/pd-cli.c:503 49 | msgid "Show extra debugging information" 50 | msgstr "Exibir informação extra de depuração" 51 | 52 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 53 | #: ../src/pd-job-impl.c:1481 54 | msgid "Not job owner" 55 | msgstr "" 56 | 57 | #: ../src/pd-job-impl.c:1279 58 | msgid "No more documents allowed" 59 | msgstr "" 60 | 61 | #: ../src/pd-job-impl.c:1289 62 | msgid "Bad AddDocumentCall" 63 | msgstr "" 64 | 65 | #: ../src/pd-job-impl.c:1521 66 | msgid "Already canceled" 67 | msgstr "" 68 | 69 | #: ../src/pd-job-impl.c:1579 70 | msgid "Cannot cancel completed job" 71 | msgstr "" 72 | 73 | #: ../src/pd-manager-impl.c:337 74 | msgid "Not found" 75 | msgstr "Não encontrado" 76 | -------------------------------------------------------------------------------- /po/pt.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # Manuela Silva , 2014 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2014-05-05 18:44+0000\n" 13 | "Last-Translator: Manuela Silva \n" 14 | "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/" 15 | "printerd/language/pt_PT/)\n" 16 | "Language: pt_PT\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 21 | 22 | #: ../data/org.freedesktop.printerd.policy.in.h:1 23 | msgid "Add a printer" 24 | msgstr "Adicione uma impressora" 25 | 26 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 27 | #: ../src/pd-manager-impl.c:300 28 | msgid "Authentication is required to add a printer" 29 | msgstr "É necessário a autenticação para adicionar uma impressora" 30 | 31 | #: ../data/org.freedesktop.printerd.policy.in.h:3 32 | msgid "Add a job" 33 | msgstr "Adicione um trabalho" 34 | 35 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 36 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 37 | msgid "Authentication is required to add a job" 38 | msgstr "É necessário a autenticação para adicionar um trabalho" 39 | 40 | #: ../data/org.freedesktop.printerd.policy.in.h:5 41 | msgid "Cancel a job" 42 | msgstr "Cancelar um trabalho" 43 | 44 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 45 | msgid "Authentication is required to cancel a job" 46 | msgstr "É necessário a autenticação para cancelar um trabalho" 47 | 48 | #: ../src/main.c:119 ../tools/pd-cli.c:503 49 | msgid "Show extra debugging information" 50 | msgstr "Mostrar informação extra da depuração" 51 | 52 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 53 | #: ../src/pd-job-impl.c:1481 54 | msgid "Not job owner" 55 | msgstr "" 56 | 57 | #: ../src/pd-job-impl.c:1279 58 | msgid "No more documents allowed" 59 | msgstr "" 60 | 61 | #: ../src/pd-job-impl.c:1289 62 | msgid "Bad AddDocumentCall" 63 | msgstr "" 64 | 65 | #: ../src/pd-job-impl.c:1521 66 | msgid "Already canceled" 67 | msgstr "" 68 | 69 | #: ../src/pd-job-impl.c:1579 70 | msgid "Cannot cancel completed job" 71 | msgstr "" 72 | 73 | #: ../src/pd-manager-impl.c:337 74 | msgid "Not found" 75 | msgstr "Não encontrado" 76 | -------------------------------------------------------------------------------- /po/uk.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # Yuri Chornoivan , 2013 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2013-11-20 10:22+0000\n" 13 | "Last-Translator: Yuri Chornoivan \n" 14 | "Language-Team: Ukrainian (http://www.transifex.com/projects/p/printerd/" 15 | "language/uk/)\n" 16 | "Language: uk\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" 21 | "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" 22 | 23 | #: ../data/org.freedesktop.printerd.policy.in.h:1 24 | msgid "Add a printer" 25 | msgstr "Додати принтер" 26 | 27 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 28 | #: ../src/pd-manager-impl.c:300 29 | msgid "Authentication is required to add a printer" 30 | msgstr "Для додавання принтера слід пройти розпізнавання" 31 | 32 | #: ../data/org.freedesktop.printerd.policy.in.h:3 33 | msgid "Add a job" 34 | msgstr "Додати завдання" 35 | 36 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 37 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 38 | msgid "Authentication is required to add a job" 39 | msgstr "Для додавання завдання слід пройти розпізнавання" 40 | 41 | #: ../data/org.freedesktop.printerd.policy.in.h:5 42 | msgid "Cancel a job" 43 | msgstr "Скасування завдання" 44 | 45 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 46 | msgid "Authentication is required to cancel a job" 47 | msgstr "Для скасування завдання слід пройти розпізнавання" 48 | 49 | #: ../src/main.c:119 ../tools/pd-cli.c:503 50 | msgid "Show extra debugging information" 51 | msgstr "Показати додаткові діагностичні дані" 52 | 53 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 54 | #: ../src/pd-job-impl.c:1481 55 | msgid "Not job owner" 56 | msgstr "" 57 | 58 | #: ../src/pd-job-impl.c:1279 59 | msgid "No more documents allowed" 60 | msgstr "" 61 | 62 | #: ../src/pd-job-impl.c:1289 63 | msgid "Bad AddDocumentCall" 64 | msgstr "" 65 | 66 | #: ../src/pd-job-impl.c:1521 67 | msgid "Already canceled" 68 | msgstr "" 69 | 70 | #: ../src/pd-job-impl.c:1579 71 | msgid "Cannot cancel completed job" 72 | msgstr "" 73 | 74 | #: ../src/pd-manager-impl.c:337 75 | msgid "Not found" 76 | msgstr "Не знайдено" 77 | -------------------------------------------------------------------------------- /po/fr.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Translators: 6 | # frizer23 , 2013 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: printerd\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2014-11-01 19:08+0000\n" 12 | "PO-Revision-Date: 2013-11-20 10:22+0000\n" 13 | "Last-Translator: frizer23 \n" 14 | "Language-Team: French (http://www.transifex.com/projects/p/printerd/language/" 15 | "fr/)\n" 16 | "Language: fr\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit\n" 20 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 21 | 22 | #: ../data/org.freedesktop.printerd.policy.in.h:1 23 | msgid "Add a printer" 24 | msgstr "Ajouter une imprimante" 25 | 26 | #: ../data/org.freedesktop.printerd.policy.in.h:2 ../src/pd-device-impl.c:303 27 | #: ../src/pd-manager-impl.c:300 28 | msgid "Authentication is required to add a printer" 29 | msgstr "Il est nécessaire de s’authentifier pour ajouter une imprimante" 30 | 31 | #: ../data/org.freedesktop.printerd.policy.in.h:3 32 | msgid "Add a job" 33 | msgstr "ajouter une tâche d’impression" 34 | 35 | #: ../data/org.freedesktop.printerd.policy.in.h:4 ../src/pd-job-impl.c:1252 36 | #: ../src/pd-job-impl.c:1337 ../src/pd-printer-impl.c:620 37 | msgid "Authentication is required to add a job" 38 | msgstr "" 39 | "il est nécessaire de s’authentifier pour ajouter une tâche d’impression" 40 | 41 | #: ../data/org.freedesktop.printerd.policy.in.h:5 42 | msgid "Cancel a job" 43 | msgstr "Annuler une tâche d’impression" 44 | 45 | #: ../data/org.freedesktop.printerd.policy.in.h:6 ../src/pd-job-impl.c:1464 46 | msgid "Authentication is required to cancel a job" 47 | msgstr "" 48 | "Il est nécessaire de s’authentifier pour annuler une tâche d’impression" 49 | 50 | #: ../src/main.c:119 ../tools/pd-cli.c:503 51 | msgid "Show extra debugging information" 52 | msgstr "Plus d’informations de débogage" 53 | 54 | #: ../src/pd-job-impl.c:1269 ../src/pd-job-impl.c:1354 55 | #: ../src/pd-job-impl.c:1481 56 | msgid "Not job owner" 57 | msgstr "" 58 | 59 | #: ../src/pd-job-impl.c:1279 60 | msgid "No more documents allowed" 61 | msgstr "" 62 | 63 | #: ../src/pd-job-impl.c:1289 64 | msgid "Bad AddDocumentCall" 65 | msgstr "" 66 | 67 | #: ../src/pd-job-impl.c:1521 68 | msgid "Already canceled" 69 | msgstr "" 70 | 71 | #: ../src/pd-job-impl.c:1579 72 | msgid "Cannot cancel completed job" 73 | msgstr "" 74 | 75 | #: ../src/pd-manager-impl.c:337 76 | msgid "Not found" 77 | msgstr "introuvable" 78 | -------------------------------------------------------------------------------- /contrib/printerd.spec.in: -------------------------------------------------------------------------------- 1 | Summary: Printer daemon 2 | Name: printerd 3 | Version: @VERSION@ 4 | Release: 0%{?dist} 5 | License: GPLv2+ 6 | URL: http://www.freedesktop.org/software/printerd/ 7 | Source0: http://www.freedesktop.org/software/printerd/releases/%{name}-%{version}.tar.xz 8 | 9 | BuildRequires: dbus-devel 10 | BuildRequires: docbook-utils 11 | BuildRequires: gettext 12 | BuildRequires: glib2-devel 13 | BuildRequires: intltool 14 | BuildRequires: libgudev1-devel 15 | BuildRequires: polkit-devel >= 0.103 16 | BuildRequires: gobject-introspection-devel 17 | 18 | Requires: systemd-units 19 | Requires(pre): shadow-utils 20 | 21 | %description 22 | printerd is a printer daemon. 23 | 24 | %package devel 25 | Summary: Development package for %{name} 26 | Requires: %{name} = %{version}-%{release} 27 | 28 | %description devel 29 | Files for development with %{name}. 30 | 31 | %prep 32 | %setup -q 33 | 34 | %build 35 | %configure \ 36 | --disable-static \ 37 | --disable-rpath \ 38 | --disable-dependency-tracking \ 39 | --with-systemdsystemunitdir=%{_unitdir} 40 | 41 | make %{?_smp_mflags} 42 | 43 | %install 44 | make install DESTDIR=$RPM_BUILD_ROOT systemdservicedir=%{_unitdir} 45 | 46 | # Remove static libs and libtool archives. 47 | find %{buildroot} -name '*.la' -exec rm -f {} ';' 48 | find %{buildroot} -name '*.a' -exec rm -f {} ';' 49 | 50 | %find_lang %{name} 51 | 52 | %post 53 | /sbin/ldconfig 54 | %systemd_post printerd.service ippd.socket ippd.service 55 | 56 | %preun 57 | %systemd_preun printerd.service ippd.socket ippd.service 58 | 59 | %postun 60 | %systemd_postun_with_restart printerd.service ippd.socket ippd.service 61 | /sbin/ldconfig 62 | 63 | %files -f %{name}.lang 64 | %defattr(-,root,root,-) 65 | %doc README.md TESTS.md AUTHORS NEWS COPYING 66 | %{_libexecdir}/printerd 67 | %{_libexecdir}/ippd 68 | %{_bindir}/* 69 | %{_sysconfdir}/dbus-1/system.d/org.freedesktop.printerd.conf 70 | #%{_datadir}/dbus-1/interfaces/org.freedesktop.printerd*.xml 71 | %{_datadir}/polkit-1/actions/org.freedesktop.printerd.policy 72 | %{_datadir}/dbus-1/system-services/org.freedesktop.printerd.service 73 | #%{_datadir}/man/man1/*.1.gz 74 | %{_libdir}/libprinterd.so.* 75 | #%config %{_sysconfdir}/printerd.conf 76 | #/lib/udev/rules.d/*.rules 77 | %{_libdir}/girepository-1.0/*.typelib 78 | %{_unitdir}/*.service 79 | %{_unitdir}/*.socket 80 | 81 | %files devel 82 | %defattr(-,root,root,-) 83 | %{_includedir}/printerd 84 | %{_libdir}/libprinterd.so 85 | %{_libdir}/pkgconfig/printerd.pc 86 | %{_datadir}/gir-1.0/*.gir 87 | 88 | %changelog 89 | * Wed Dec 3 2014 Richard Hughes @VERSION@-0 90 | - Update from git 91 | 92 | -------------------------------------------------------------------------------- /tests/createprinter1/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Create a printer. 6 | printf "CreatePrinter\n" 7 | result=$(gdbus call --session \ 8 | --dest $PD_DEST \ 9 | --object-path $PD_PATH/Manager \ 10 | --method $PD_IFACE.Manager.CreatePrinter \ 11 | "{}" \ 12 | "create-printer1" \ 13 | "printer description" \ 14 | "printer location" \ 15 | '["ipp://remote:631/printers/remote"]' \ 16 | "{}") 17 | 18 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 19 | if [ -z "$objpath" ]; then 20 | printf "Expected (objectpath): %s\n" "$result" 21 | result_is 1 22 | fi 23 | 24 | # Verify its properties. 25 | printf "Examining %s\n" "$objpath" 26 | if ! diff -u - <(gdbus introspect --session --only-properties \ 27 | --dest $PD_DEST \ 28 | --object-path "$objpath" | \ 29 | grep ' = ' | LC_ALL=C sort | \ 30 | sed \ 31 | -e 's,^ *readonly ,,' \ 32 | -e '/^b IsDefault /d' \ 33 | -e '/^s Driver /d') << "EOF" 34 | ao ActiveJobs = []; 35 | as DeviceUris = ['ipp://remote:631/printers/remote']; 36 | as StateReasons = []; 37 | a{sv} Defaults = {'media': <'iso-a4'>, 'document-format': <'application/octet-stream'>}; 38 | a{sv} Supported = {'media': <['iso-a4', 'na-letter']>, 'document-format': <['application/pdf']>}; 39 | b IsAcceptingJobs = false; 40 | b IsShared = false; 41 | s Description = 'printer description'; 42 | s Ieee1284Id = ''; 43 | s Location = 'printer location'; 44 | s Name = 'create-printer1'; 45 | u State = 3; 46 | EOF 47 | then 48 | printf "Created properties differ from expected\n" 49 | result_is 1 50 | fi 51 | 52 | # Now delete it. 53 | printf "DeletePrinter\n" 54 | result=$(gdbus call --session \ 55 | --dest $PD_DEST \ 56 | --object-path $PD_PATH/Manager \ 57 | --method $PD_IFACE.Manager.DeletePrinter \ 58 | "{}" \ 59 | "$objpath") 60 | 61 | if [ "$result" != "()" ]; then 62 | printf "Expected (): %s\n" "$result" 63 | result_is 1 64 | fi 65 | 66 | # Try examining it: should fail. 67 | printf "Examining %s\n" "$objpath" 68 | result=$(gdbus introspect --session --only-properties \ 69 | --dest $PD_DEST \ 70 | --object-path "$objpath" 2>/dev/null | grep ' = ') 71 | if [ -n "$result" ]; then 72 | printf "Expected no properties introspecting deleted printer\n" 73 | result_is 1 74 | fi 75 | 76 | # Try deleting it a second time: should fail. 77 | printf "DeletePrinter\n" 78 | if gdbus call --session \ 79 | --dest $PD_DEST \ 80 | --object-path $PD_PATH/Manager \ 81 | --method $PD_IFACE.Manager.DeletePrinter \ 82 | "{}" \ 83 | $objpath 2>/dev/null; then 84 | printf "Expected failure for second DeletePrinter call\n" 85 | result_is 1 86 | fi 87 | 88 | result_is 0 89 | -------------------------------------------------------------------------------- /tests/job4/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Test "file:" output 6 | 7 | INPUT_FILE="$(mktemp /tmp/printerd.XXXXXXXXX)" 8 | FILE_TARGET="$(mktemp /tmp/printerd.XXXXXXXXX)" 9 | function finish { 10 | rm -f "$INPUT_FILE" "$FILE_TARGET" 11 | } 12 | trap finish EXIT 13 | 14 | # Create a printer. 15 | printf "CreatePrinter\n" 16 | result=$(gdbus call --session \ 17 | --dest $PD_DEST \ 18 | --object-path $PD_PATH/Manager \ 19 | --method $PD_IFACE.Manager.CreatePrinter \ 20 | "{}" \ 21 | "job4" \ 22 | "printer description" \ 23 | "printer location" \ 24 | "['file://${FILE_TARGET}']" \ 25 | "{}") 26 | 27 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 28 | if [ -z "$objpath" ]; then 29 | printf "Expected (objectpath): %s\n" "$result" 30 | result_is 1 31 | fi 32 | 33 | # Create a job on that printer. 34 | printf "CreateJob\n" 35 | result=$(gdbus call --session \ 36 | --dest $PD_DEST \ 37 | --object-path $objpath \ 38 | --method $PD_IFACE.Printer.CreateJob \ 39 | '{}' \ 40 | 'job4' \ 41 | '{}') 42 | if ! diff -u - <(printf "%s\n" "$result" | sed -e 's,[0-9]\+,X,') <<"EOF" 43 | (objectpath '/org/freedesktop/printerd/job/X', @a{sv} {}) 44 | EOF 45 | then 46 | printf "Unexpected result\n" 47 | result_is 1 48 | fi 49 | 50 | # Add a document to it. 51 | jobpath=$(printf "%s" "$result" | sed -ne "s:^.*'\(.*\)'.*$:\1:p") 52 | printf "AddDocument\n" 53 | printf "Text file\n" > "$INPUT_FILE" 54 | if ! $PDCLI --session add-documents "${jobpath##*/}" "$INPUT_FILE"; then 55 | printf "Failed to add document to job\n" 56 | result_is 1 57 | fi 58 | 59 | # Start the job 60 | printf "Start\n" 61 | result=$(gdbus call --session \ 62 | --dest $PD_DEST \ 63 | --object-path $jobpath \ 64 | --method $PD_IFACE.Job.Start \ 65 | '{}') 66 | if [ "$result" != "" ]; then 67 | printf "StartJob should have failed but did not\n" 68 | result_is 1 69 | fi 70 | 71 | # Inspect its properties. State should be cancelled. 72 | printf "Examining properties\n" 73 | if ! diff -u - <(gdbus introspect --session --only-properties \ 74 | --dest $PD_DEST \ 75 | --object-path "$jobpath" | \ 76 | grep 'u State = ' | \ 77 | sed -e 's,^ *readonly ,,') < $@ 31 | 32 | #pd-daemon-marshal.c: pd-daemon-marshal.list 33 | # echo "#include \"pd-daemon-marshal.h\"" > $@ && glib-genmarshal $< --prefix=pd_daemon_marshal --body >> $@ 34 | 35 | #EXTRA_DIST += pd-daemon-marshal.list 36 | 37 | # ---------------------------------------------------------------------- 38 | 39 | noinst_LTLIBRARIES = libprinterddaemon.la 40 | 41 | libprinterddaemon_la_SOURCES = \ 42 | pd-common.h \ 43 | pd-common.c \ 44 | pd-daemontypes.h \ 45 | pd-daemon.h \ 46 | pd-daemon.c \ 47 | pd-engine.h \ 48 | pd-engine.c \ 49 | pd-manager-impl.h \ 50 | pd-manager-impl.c \ 51 | pd-device-impl.h \ 52 | pd-device-impl.c \ 53 | pd-printer-impl.h \ 54 | pd-printer-impl.c \ 55 | pd-job-impl.h \ 56 | pd-job-impl.c \ 57 | pd-log.h \ 58 | $(BUILT_SOURCES) 59 | 60 | libprinterddaemon_la_CFLAGS = \ 61 | -I$(top_srcdir) \ 62 | -DG_LOG_DOMAIN=\"printerd\" \ 63 | $(GLIB_CFLAGS) \ 64 | $(GIO_CFLAGS) \ 65 | $(GUDEV_CFLAGS) \ 66 | $(POLKIT_GOBJECT_1_CFLAGS) \ 67 | $(CUPS_CFLAGS) \ 68 | $(NULL) 69 | 70 | libprinterddaemon_la_LIBADD = \ 71 | $(GLIB_LIBS) \ 72 | $(GIO_LIBS) \ 73 | $(GUDEV_LIBS) \ 74 | $(POLKIT_GOBJECT_1_LIBS) \ 75 | $(CUPS_LIBS) \ 76 | $(top_builddir)/printerd/libprinterd.la \ 77 | $(NULL) 78 | 79 | # ---------------------------------------------------------------------- 80 | 81 | libexec_PROGRAMS = printerd 82 | 83 | printerd_SOURCES = \ 84 | main.c \ 85 | $(NULL) 86 | 87 | printerd_CFLAGS = \ 88 | -DG_LOG_DOMAIN=\"printerd\" \ 89 | $(NULL) 90 | 91 | printerd_LDADD = \ 92 | $(GLIB_LIBS) \ 93 | $(GIO_LIBS) \ 94 | libprinterddaemon.la \ 95 | $(SYSTEMD_LIBS) \ 96 | $(NULL) 97 | 98 | # ---------------------------------------------------------------------- 99 | 100 | -include $(top_srcdir)/git.mk 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | printerd 2 | ======== 3 | 4 | printerd is a daemon to manage local and remote printers on Linux. 5 | 6 | It is a polkit-aware system activatable D-Bus service. 7 | 8 | To play around with it, after running 'make install' you can run the 9 | daemon as root in verbose mode from the command line: 10 | 11 | ``` 12 | su -c '/usr/local/libexec/printerd -v' 13 | ``` 14 | 15 | Now you can interact with it using the supplied `pd-client` and 16 | `pd-view` tools, or with [d-feet](http://live.gnome.org/DFeet/), 17 | or with the "gdbus" tool: 18 | 19 | ``` 20 | gdbus monitor --system --dest org.freedesktop.printerd 21 | ``` 22 | 23 | Note that currently there is no SELinux policy for printerd so when 24 | submitting files for printing you will need to enable permissive mode 25 | using `setenforce 0`. 26 | 27 | The D-Bus objects are: 28 | 29 | * Manager: for creating print queues with a specific device URI 30 | * Device: a detected printer device 31 | * Printer: a print queue 32 | * Job: a print job 33 | 34 | The Device object provides a method for creating a Printer object for 35 | it. The Printer object provides a method for creating a job. 36 | 37 | To print a file, the Printer object's CreateJob method is called. 38 | This returns an object path for the new job. The new Job object's 39 | AddDocument method is used to add a file to the job, and finally the 40 | Job object's Start method is used to allow the job to be processed. 41 | 42 | The core IPP concepts are used for job and printer states, state 43 | reasons, and so on. The plan is that an IPP server could be built 44 | out-of-process, which would be a client for the printerd D-Bus 45 | interface. 46 | 47 | Translations can be submitted at [Transifex](https://www.transifex.com/projects/p/printerd/). 48 | 49 | Structure 50 | --------- 51 | 52 | The `data/` directory contains: 53 | * the D-Bus interface, configuration, and service definition, 54 | * the polkit configuration, and 55 | * the systemd service file 56 | 57 | in the `printerd/` directory is client code for communicating with 58 | printerd from C and using GObject introspection, as well as code 59 | generated from the interface definition. 60 | 61 | The service implementation lives in the `src/` directory. The service 62 | is implemented using GDBusObjectManager to export the various objects 63 | to D-Bus. This involves having skeleton objects such as PdJob, which 64 | hold the properties defined in the interface, and implementation 65 | objects such as PdJobImpl (inheriting from PdJob) which provide the 66 | method implementations. 67 | 68 | The Printer and Device objects set a flag telling the 69 | GDBusObjectManager to handle each D-Bus method invocation in its own 70 | thread. The Job object handles all method invocations in the main 71 | context. 72 | 73 | Orchestrating the Device, Printer, and Job objects is the 74 | PdEngine. The engine decides on actions, for example when to start 75 | jobs. 76 | 77 | IPP support is provided in the `ippd/` directory. This works by 78 | running a Python http.server handling the IPP requests by backing them 79 | with calls into printerd. 80 | -------------------------------------------------------------------------------- /tests/job1/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | FILE_TARGET="$(mktemp /tmp/printerd.XXXXXXXXX)" 6 | function finish { 7 | rm -f "$FILE_TARGET" 8 | } 9 | trap finish EXIT 10 | 11 | # Create a printer. 12 | printf "CreatePrinter\n" 13 | result=$(gdbus call --session \ 14 | --dest $PD_DEST \ 15 | --object-path $PD_PATH/Manager \ 16 | --method $PD_IFACE.Manager.CreatePrinter \ 17 | "{}" \ 18 | "job1" \ 19 | "printer description" \ 20 | "printer location" \ 21 | "['file://${FILE_TARGET}']" \ 22 | "{}") 23 | 24 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 25 | if [ -z "$objpath" ]; then 26 | printf "Expected (objectpath): %s\n" "$result" 27 | result_is 1 28 | fi 29 | 30 | # Create a job on that printer. 31 | printf "CreateJob\n" 32 | result=$(gdbus call --session \ 33 | --dest $PD_DEST \ 34 | --object-path $objpath \ 35 | --method $PD_IFACE.Printer.CreateJob \ 36 | '{}' \ 37 | 'job1' \ 38 | '{}') 39 | if ! diff -u - <(printf "%s\n" "$result" | sed -e 's,[0-9]\+,X,') <<"EOF" 40 | (objectpath '/org/freedesktop/printerd/job/X', @a{sv} {}) 41 | EOF 42 | then 43 | printf "Unexpected result\n" 44 | result_is 1 45 | fi 46 | 47 | # Inspect its properties 48 | jobpath=$(printf "%s" "$result" | sed -ne "s:^.*'\(.*\)'.*$:\1:p") 49 | if ! diff -u - <(gdbus introspect --session --only-properties \ 50 | --dest $PD_DEST \ 51 | --object-path "$jobpath" | \ 52 | grep ' = ' | LC_ALL=C sort | \ 53 | sed \ 54 | -e 's,^ *readonly ,,' \ 55 | -e '/u Id /d' \ 56 | -e '/a{sv} Attributes /d' \ 57 | -e '/s DeviceUri /d') < 4 | * Copyright (C) 2014 Tim Waugh 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | * 20 | */ 21 | 22 | #ifndef __PD_ENGINE_H__ 23 | #define __PD_ENGINE_H__ 24 | 25 | #include "pd-daemontypes.h" 26 | 27 | G_BEGIN_DECLS 28 | 29 | #define PD_TYPE_ENGINE (pd_engine_get_type ()) 30 | #define PD_ENGINE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PD_TYPE_ENGINE, PdEngine)) 31 | #define PD_ENGINE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PD_TYPE_ENGINE, PdEngineClass)) 32 | #define PD_ENGINE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PD_TYPE_ENGINE, PdEngineClass)) 33 | #define PD_IS_ENGINE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PD_TYPE_ENGINE)) 34 | #define PD_IS_ENGINE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PD_TYPE_ENGINE)) 35 | 36 | typedef struct _PdEngineClass PdEngineClass; 37 | typedef struct _PdEnginePrivate PdEnginePrivate; 38 | 39 | /** 40 | * PdEngine: 41 | * 42 | * The #PdEngine structure contains only private data and 43 | * should only be accessed using the provided API. 44 | */ 45 | struct _PdEngine 46 | { 47 | /*< private >*/ 48 | GObject parent_instance; 49 | PdEnginePrivate *priv; 50 | }; 51 | 52 | /** 53 | * PdEngineClass: 54 | * @parent_class: The parent class. 55 | * @start: Virtual function for pd_engine_start(). The default implementation does nothing. 56 | * 57 | * Class structure for #PdEngine. 58 | */ 59 | struct _PdEngineClass 60 | { 61 | GObjectClass parent_class; 62 | /*< private >*/ 63 | gpointer padding[8]; 64 | }; 65 | 66 | 67 | GType pd_engine_get_type (void) G_GNUC_CONST; 68 | PdEngine *pd_engine_new (PdDaemon *daemon); 69 | PdDaemon *pd_engine_get_daemon (PdEngine *engine); 70 | GUdevClient *pd_engine_get_udev_client (PdEngine *engine); 71 | GList *pd_engine_dup_printer_ids (PdEngine *engine); 72 | GList *pd_engine_get_devices (PdEngine *engine); 73 | void pd_engine_start (PdEngine *engine); 74 | PdPrinter *pd_engine_add_printer (PdEngine *engine, 75 | GVariant *options, 76 | const gchar *name, 77 | const gchar *description, 78 | const gchar *location, 79 | const gchar *ieee1284_id, 80 | GError **error); 81 | gboolean pd_engine_remove_printer (PdEngine *engine, 82 | const gchar *printer_path); 83 | PdPrinter *pd_engine_get_printer_by_path (PdEngine *engine, 84 | const gchar *printer_path); 85 | PdJob *pd_engine_add_job (PdEngine *engine, 86 | const gchar *printer_path, 87 | const gchar *name, 88 | GVariant *attributes); 89 | gboolean pd_engine_remove_job (PdEngine *engine, 90 | const gchar *job_path); 91 | G_END_DECLS 92 | 93 | #endif /* __PD_ENGINE_H__ */ 94 | -------------------------------------------------------------------------------- /tests/createprinter3/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Create a printer. 6 | printf "CreatePrinter\n" 7 | result=$(gdbus call --session \ 8 | --dest $PD_DEST \ 9 | --object-path $PD_PATH/Manager \ 10 | --method $PD_IFACE.Manager.CreatePrinter \ 11 | "{}" \ 12 | "create-printer3" \ 13 | "printer description" \ 14 | "printer location" \ 15 | '["ipp://remote:631/printers/remote"]' \ 16 | "{}") 17 | 18 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 19 | if [ -z "$objpath" ]; then 20 | printf "Expected (objectpath): %s\n" "$result" 21 | result_is 1 22 | fi 23 | 24 | # Save Defaults to check ResetDefaults later 25 | Defaults=$(gdbus introspect --session --only-properties \ 26 | --dest $PD_DEST \ 27 | --object-path "$objpath" | \ 28 | grep ' Defaults = ' | \ 29 | sed -e 's,^ *readonly a{sv} Defaults = {,,' \ 30 | -e 's,};$,,' \ 31 | -e 's:>, :>\n:g' | \ 32 | LC_ALL=C sort) 33 | 34 | # Next try UpdateDefaults 35 | printf "UpdateDefaults\n" 36 | result=$(gdbus call --session \ 37 | --dest $PD_DEST \ 38 | --object-path "$objpath" \ 39 | --method $PD_IFACE.Printer.UpdateDefaults \ 40 | "{'print-quality':<5>,'media':<'na-letter'>}") 41 | 42 | if [ "$result" != "()" ]; then 43 | printf "Expected (): %s\n" "$result" 44 | result_is 1 45 | fi 46 | 47 | # Verify it worked. 48 | printf "Examining %s\n" "$objpath" 49 | if ! diff -u - <(gdbus introspect --session --only-properties \ 50 | --dest $PD_DEST \ 51 | --object-path "$objpath" | \ 52 | grep ' Defaults = ' | \ 53 | sed -e 's,^ *readonly a{sv} Defaults = {,,' \ 54 | -e 's,};$,,' \ 55 | -e 's:>, :>\n:g' | \ 56 | LC_ALL=C sort) << "EOF" 57 | 'document-format': <'application/octet-stream'> 58 | 'media': <'na-letter'> 59 | 'print-quality': <5> 60 | EOF 61 | then 62 | printf "Defaults property differs from expected\n" 63 | result_is 1 64 | fi 65 | 66 | # Try ResetDefaults 67 | printf "ResetDefaults\n" 68 | result=$(gdbus call --session \ 69 | --dest $PD_DEST \ 70 | --object-path "$objpath" \ 71 | --method $PD_IFACE.Printer.ResetDefaults \ 72 | '["print-quality","media","document-format"]') 73 | 74 | if [ "$result" != "()" ]; then 75 | printf "Expected (): %s\n" "$result" 76 | result_is 1 77 | fi 78 | 79 | if diff -u <(gdbus introspect --session --only-properties \ 80 | --dest $PD_DEST \ 81 | --object-path "$objpath" | \ 82 | grep ' Defaults = ' | \ 83 | sed -e 's,^ *readonly a{sv} Defaults = {,,' \ 84 | -e 's,};$,,' \ 85 | -e 's:>, :>\n:g' | \ 86 | LC_ALL=C sort) < 4 | * Copyright (C) 2014 Tim Waugh 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General 17 | * Public License along with this library; if not, write to the 18 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 19 | * Boston, MA 02111-1307, USA. 20 | */ 21 | 22 | #if !defined (__PD_INSIDE_PRINTERD_H__) && !defined (PRINTERD_COMPILATION) 23 | #error "Only can be included directly." 24 | #endif 25 | 26 | #ifndef __PD_ENUMS_H__ 27 | #define __PD_ENUMS_H__ 28 | 29 | #include 30 | 31 | G_BEGIN_DECLS 32 | 33 | /** 34 | * PdError: 35 | * @PD_ERROR_FAILED: The operation failed. 36 | * @PD_ERROR_CANCELLED: The operation was cancelled. 37 | * @PD_ERROR_UNIMPLEMENTED: The operation is not implemented. 38 | * @PD_ERROR_UNSUPPORTED_DOCUMENT_TYPE: The document type is not supported. 39 | * 40 | * Error codes for the #PD_ERROR error domain and the 41 | * corresponding D-Bus error names. 42 | */ 43 | typedef enum 44 | { 45 | PD_ERROR_FAILED, /* org.freedesktop.printerd.Error.Failed */ 46 | PD_ERROR_CANCELLED, /* org.freedesktop.printerd.Error.Cancelled */ 47 | PD_ERROR_UNIMPLEMENTED, /* org.freedesktop.printerd.Error.Unimplemented */ 48 | PD_ERROR_UNSUPPORTED_DOCUMENT_TYPE, /* org.freedesktop.printerd.Error.UnsupportedDocumentType */ 49 | } PdError; 50 | 51 | #define PD_ERROR_NUM_ENTRIES (PD_ERROR_UNSUPPORTED_DOCUMENT_TYPE + 1) 52 | 53 | /** 54 | * PdPrinterState: 55 | * @PD_PRINTER_STATE_IDLE: The printer is idle. 56 | * @PD_PRINTER_STATE_PROCESSING: The printer is processing a job. 57 | * @PD_PRINTER_STATE_STOPPED: The printer is stopped. 58 | * 59 | * Printer state values (from RFC 2911). 60 | */ 61 | typedef enum 62 | { 63 | PD_PRINTER_STATE_IDLE = 3, 64 | PD_PRINTER_STATE_PROCESSING, 65 | PD_PRINTER_STATE_STOPPED, 66 | } PdPrinterState; 67 | 68 | /** 69 | * PdJobState: 70 | * @PD_JOB_STATE_PENDING: Candidate to start processing. 71 | * @PD_JOB_STATE_PENDING_HELD: There are reasons not to process this job. 72 | * @PD_JOB_STATE_PROCESSING: Job running. 73 | * @PD_JOB_STATE_PROCESSING_STOPPED: Processing is paused. 74 | * @PD_JOB_STATE_CANCELED: Terminal state, canceled. 75 | * @PD_JOB_STATE_ABORTED: Terminal state, aborted on error. 76 | * @PD_JOB_STATE_COMPLETED: Terminal state, normal completion. 77 | * 78 | * Job state values (from RFC 2911). 79 | */ 80 | typedef enum 81 | { 82 | PD_JOB_STATE_PENDING = 3, /* candidate to start processing */ 83 | PD_JOB_STATE_PENDING_HELD, /* reasons not to process */ 84 | PD_JOB_STATE_PROCESSING, /* job running */ 85 | PD_JOB_STATE_PROCESSING_STOPPED,/* processing is paused */ 86 | PD_JOB_STATE_CANCELED, /* terminal state */ 87 | PD_JOB_STATE_ABORTED, /* terminal state */ 88 | PD_JOB_STATE_COMPLETED, /* terminal state */ 89 | } PdJobState; 90 | 91 | G_END_DECLS 92 | 93 | #endif /* __PD_ENUMS_H__ */ 94 | -------------------------------------------------------------------------------- /tests/filter1/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Test filtering to aplication/vnd.cups-raster 6 | 7 | PPD="$(simple_ppd "application/vnd.cups-raster 0 -")" 8 | INPUT_FILE="$(sample_pdf)" 9 | FILE_TARGET="$(mktemp /tmp/printerd.XXXXXXXXX)" 10 | function finish { 11 | rm -f "$PPD" "$INPUT_FILE" "$FILE_TARGET" 12 | } 13 | trap finish EXIT 14 | 15 | # Create a printer. 16 | printf "CreatePrinter driver:%s\n" "${PPD}" 17 | result=$(gdbus call --session \ 18 | --dest $PD_DEST \ 19 | --object-path $PD_PATH/Manager \ 20 | --method $PD_IFACE.Manager.CreatePrinter \ 21 | "{'driver-name':<'${PPD}'>}" \ 22 | "filter1" \ 23 | "printer description" \ 24 | "printer location" \ 25 | "['file://${FILE_TARGET}']" \ 26 | "{}") 27 | 28 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 29 | if [ -z "$objpath" ]; then 30 | printf "Expected (objectpath): %s\n" "$result" 31 | result_is 1 32 | fi 33 | 34 | # Create a job on that printer. 35 | printf "CreateJob\n" 36 | result=$(gdbus call --session \ 37 | --dest $PD_DEST \ 38 | --object-path $objpath \ 39 | --method $PD_IFACE.Printer.CreateJob \ 40 | "{}" \ 41 | 'filter1' \ 42 | '{}') 43 | if ! diff -u - <(printf "%s\n" "$result" | sed -e 's,[0-9]\+,X,') <<"EOF" 44 | (objectpath '/org/freedesktop/printerd/job/X', @a{sv} {}) 45 | EOF 46 | then 47 | printf "Unexpected result\n" 48 | result_is 1 49 | fi 50 | 51 | # Add a document to it. 52 | jobpath=$(printf "%s" "$result" | sed -ne "s:^.*'\(.*\)'.*$:\1:p") 53 | printf "AddDocument\n" 54 | if ! $PDCLI --session add-documents "${jobpath##*/}" "$INPUT_FILE"; then 55 | printf "Failed to add document to job\n" 56 | result_is 1 57 | fi 58 | 59 | # Start the job 60 | printf "Start\n" 61 | result=$(gdbus call --session \ 62 | --dest $PD_DEST \ 63 | --object-path $jobpath \ 64 | --method $PD_IFACE.Job.Start \ 65 | '{}') 66 | if [ "$result" != "()" ]; then 67 | printf "StartJob failed\n" 68 | result_is 1 69 | fi 70 | 71 | # Wait for the job to complete 72 | for i in 0.2 0.3 0.5 1 1 1 1; do 73 | sleep $i 74 | # Inspect its properties. State should be completed. 75 | printf "Examining properties\n" 76 | if diff -qu - <(gdbus introspect --session --only-properties \ 77 | --dest $PD_DEST \ 78 | --object-path "$jobpath" | \ 79 | grep 'u State = ' | \ 80 | sed -e 's,^ *readonly ,,') </dev/null)" 102 | if [ "$MAGIC" != "3SaR" ]; then 103 | printf "Output file magic differs from expected\n" 104 | result_is 1 105 | fi 106 | printf "Magic: %s\n" "$MAGIC" 107 | 108 | # Delete the printer. 109 | printf "DeletePrinter\n" 110 | result=$(gdbus call --session \ 111 | --dest $PD_DEST \ 112 | --object-path $PD_PATH/Manager \ 113 | --method $PD_IFACE.Manager.DeletePrinter \ 114 | "{}" \ 115 | $objpath) 116 | 117 | if [ "$result" != "()" ]; then 118 | printf "Expected (): %s\n" "$result" 119 | result_is 1 120 | fi 121 | 122 | result_is 0 123 | -------------------------------------------------------------------------------- /tests/filter2/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Test filtering beyond aplication/vnd.cups-raster 6 | 7 | PPD="$(simple_ppd "application/vnd.cups-raster 0 rastertopclx")" 8 | INPUT_FILE="$(sample_pdf)" 9 | FILE_TARGET="$(mktemp /tmp/printerd.XXXXXXXXX)" 10 | function finish { 11 | rm -f "$PPD" "$INPUT_FILE" "$FILE_TARGET" 12 | } 13 | trap finish EXIT 14 | 15 | # Create a printer. 16 | printf "CreatePrinter driver:%s\n" "${PPD}" 17 | result=$(gdbus call --session \ 18 | --dest $PD_DEST \ 19 | --object-path $PD_PATH/Manager \ 20 | --method $PD_IFACE.Manager.CreatePrinter \ 21 | "{'driver-name':<'${PPD}'>}" \ 22 | "filter2" \ 23 | "printer description" \ 24 | "printer location" \ 25 | "['file://${FILE_TARGET}']" \ 26 | "{}") 27 | 28 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 29 | if [ -z "$objpath" ]; then 30 | printf "Expected (objectpath): %s\n" "$result" 31 | result_is 1 32 | fi 33 | 34 | # Create a job on that printer. 35 | printf "CreateJob\n" 36 | result=$(gdbus call --session \ 37 | --dest $PD_DEST \ 38 | --object-path $objpath \ 39 | --method $PD_IFACE.Printer.CreateJob \ 40 | "{}" \ 41 | 'filter2' \ 42 | '{}') 43 | if ! diff -u - <(printf "%s\n" "$result" | sed -e 's,[0-9]\+,X,') <<"EOF" 44 | (objectpath '/org/freedesktop/printerd/job/X', @a{sv} {}) 45 | EOF 46 | then 47 | printf "Unexpected result\n" 48 | result_is 1 49 | fi 50 | 51 | # Add a document to it. 52 | jobpath=$(printf "%s" "$result" | sed -ne "s:^.*'\(.*\)'.*$:\1:p") 53 | printf "AddDocument\n" 54 | if ! $PDCLI --session add-documents "${jobpath##*/}" "$INPUT_FILE"; then 55 | printf "Failed to add document to job\n" 56 | result_is 1 57 | fi 58 | 59 | # Start the job 60 | printf "Start\n" 61 | result=$(gdbus call --session \ 62 | --dest $PD_DEST \ 63 | --object-path $jobpath \ 64 | --method $PD_IFACE.Job.Start \ 65 | '{}') 66 | if [ "$result" != "()" ]; then 67 | printf "StartJob failed\n" 68 | result_is 1 69 | fi 70 | 71 | # Wait for the job to complete 72 | for i in 0.2 0.3 0.5 1 1 1 1; do 73 | sleep $i 74 | # Inspect its properties. State should be completed. 75 | printf "Examining properties\n" 76 | if diff -qu - <(gdbus introspect --session --only-properties \ 77 | --dest $PD_DEST \ 78 | --object-path "$jobpath" | \ 79 | grep 'u State = ' | \ 80 | sed -e 's,^ *readonly ,,') </dev/null)" 102 | if [ "$ESC" != "$(printf '\x1b')" ]; then 103 | printf "Output file first byte differs from expected\n" 104 | result_is 1 105 | fi 106 | printf "ESC: %s\n" "$(cat -v <<<"$ESC")" 107 | 108 | # Delete the printer. 109 | printf "DeletePrinter\n" 110 | result=$(gdbus call --session \ 111 | --dest $PD_DEST \ 112 | --object-path $PD_PATH/Manager \ 113 | --method $PD_IFACE.Manager.DeletePrinter \ 114 | "{}" \ 115 | $objpath) 116 | 117 | if [ "$result" != "()" ]; then 118 | printf "Expected (): %s\n" "$result" 119 | result_is 1 120 | fi 121 | 122 | result_is 0 123 | -------------------------------------------------------------------------------- /tests/job2/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Test "file:" output 6 | 7 | INPUT_FILE="$(sample_pdf)" 8 | FILE_TARGET="$(mktemp /tmp/printerd.XXXXXXXXX)" 9 | function finish { 10 | rm -f "$INPUT_FILE" "$FILE_TARGET" 11 | } 12 | trap finish EXIT 13 | 14 | # Create a printer. 15 | printf "CreatePrinter\n" 16 | result=$(gdbus call --session \ 17 | --dest $PD_DEST \ 18 | --object-path $PD_PATH/Manager \ 19 | --method $PD_IFACE.Manager.CreatePrinter \ 20 | "{}" \ 21 | "job2" \ 22 | "printer description" \ 23 | "printer location" \ 24 | "['file://${FILE_TARGET}']" \ 25 | "{}") 26 | 27 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 28 | if [ -z "$objpath" ]; then 29 | printf "Expected (objectpath): %s\n" "$result" 30 | result_is 1 31 | fi 32 | 33 | # Create a job on that printer. 34 | printf "CreateJob\n" 35 | result=$(gdbus call --session \ 36 | --dest $PD_DEST \ 37 | --object-path $objpath \ 38 | --method $PD_IFACE.Printer.CreateJob \ 39 | '{}' \ 40 | 'job2' \ 41 | '{}') 42 | if ! diff -u - <(printf "%s\n" "$result" | sed -e 's,[0-9]\+,X,') <<"EOF" 43 | (objectpath '/org/freedesktop/printerd/job/X', @a{sv} {}) 44 | EOF 45 | then 46 | printf "Unexpected result\n" 47 | result_is 1 48 | fi 49 | 50 | # Add a document to it. 51 | jobpath=$(printf "%s" "$result" | sed -ne "s:^.*'\(.*\)'.*$:\1:p") 52 | printf "AddDocument\n" 53 | if ! $PDCLI --session add-documents "${jobpath##*/}" "$INPUT_FILE"; then 54 | printf "Failed to add document to job\n" 55 | result_is 1 56 | fi 57 | 58 | # Start the job 59 | printf "Start\n" 60 | result=$(gdbus call --session \ 61 | --dest $PD_DEST \ 62 | --object-path $jobpath \ 63 | --method $PD_IFACE.Job.Start \ 64 | '{}') 65 | if [ "$result" != "()" ]; then 66 | printf "Failed to start job\n" 67 | result_is 1 68 | fi 69 | 70 | # Wait for the job to complete 71 | for i in 0.2 0.3 0.5 1 1 1 1; do 72 | sleep $i 73 | # Inspect its properties. State should be completed. 74 | printf "Examining properties\n" 75 | if diff -qu - <(gdbus introspect --session --only-properties \ 76 | --dest $PD_DEST \ 77 | --object-path "$jobpath" | \ 78 | grep 'u State = ' | \ 79 | sed -e 's,^ *readonly ,,') </dev/null; then 133 | printf "Expected cancel of completed job to fail\n" 134 | result_is 1 135 | fi 136 | 137 | # Delete the printer. 138 | printf "DeletePrinter\n" 139 | result=$(gdbus call --session \ 140 | --dest $PD_DEST \ 141 | --object-path $PD_PATH/Manager \ 142 | --method $PD_IFACE.Manager.DeletePrinter \ 143 | "{}" \ 144 | $objpath) 145 | 146 | if [ "$result" != "()" ]; then 147 | printf "Expected (): %s\n" "$result" 148 | result_is 1 149 | fi 150 | 151 | result_is 0 152 | -------------------------------------------------------------------------------- /tests/job3/run-test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . "${top_srcdir-.}"/tests/common.sh 4 | 5 | # Test "file:" output 6 | 7 | INPUT_FILE="$(sample_pdf)" 8 | FILE_TARGET="$(mktemp /tmp/printerd.XXXXXXXXX)" 9 | function finish { 10 | rm -f "$INPUT_FILE" "$FILE_TARGET" 11 | } 12 | trap finish EXIT 13 | 14 | # Create a printer. 15 | printf "CreatePrinter\n" 16 | result=$(gdbus call --session \ 17 | --dest $PD_DEST \ 18 | --object-path $PD_PATH/Manager \ 19 | --method $PD_IFACE.Manager.CreatePrinter \ 20 | "{}" \ 21 | "job3" \ 22 | "printer description" \ 23 | "printer location" \ 24 | "['file://${FILE_TARGET}?wait=1']" \ 25 | "{}") 26 | 27 | objpath=$(printf "%s" "$result" | sed -ne "s:^(objectpath '\(.*\)',):\1:p") 28 | if [ -z "$objpath" ]; then 29 | printf "Expected (objectpath): %s\n" "$result" 30 | result_is 1 31 | fi 32 | 33 | # Create a job on that printer. 34 | printf "CreateJob\n" 35 | result=$(gdbus call --session \ 36 | --dest $PD_DEST \ 37 | --object-path $objpath \ 38 | --method $PD_IFACE.Printer.CreateJob \ 39 | '{}' \ 40 | 'job3' \ 41 | '{}') 42 | if ! diff -u - <(printf "%s\n" "$result" | sed -e 's,[0-9]\+,X,') <<"EOF" 43 | (objectpath '/org/freedesktop/printerd/job/X', @a{sv} {}) 44 | EOF 45 | then 46 | printf "Unexpected result\n" 47 | result_is 1 48 | fi 49 | 50 | # Add a document to it. 51 | jobpath=$(printf "%s" "$result" | sed -ne "s:^.*'\(.*\)'.*$:\1:p") 52 | printf "AddDocument %s\n" "$jobpath" 53 | if ! $PDCLI --session add-documents "${jobpath##*/}" "$INPUT_FILE"; then 54 | printf "Failed to add document to job\n" 55 | result_is 1 56 | fi 57 | 58 | # Start the job 59 | printf "Start\n" 60 | result=$(gdbus call --session \ 61 | --dest $PD_DEST \ 62 | --object-path $jobpath \ 63 | --method $PD_IFACE.Job.Start \ 64 | '{}') 65 | if [ "$result" != "()" ]; then 66 | printf "Failed to start job\n" 67 | result_is 1 68 | fi 69 | 70 | # Wait for the job to complete 71 | for i in 0.2 0.3 0.5 1 1 1 1; do 72 | sleep $i 73 | # Inspect its properties. State should be completed. 74 | printf "Examining properties\n" 75 | if diff -qu - <(gdbus introspect --session --only-properties \ 76 | --dest $PD_DEST \ 77 | --object-path "$jobpath" | \ 78 | grep 'u State = ' | \ 79 | sed -e 's,^ *readonly ,,') </dev/null; then 133 | printf "Expected cancel of completed job to fail\n" 134 | result_is 1 135 | fi 136 | 137 | # Delete the printer. 138 | printf "DeletePrinter\n" 139 | result=$(gdbus call --session \ 140 | --dest $PD_DEST \ 141 | --object-path $PD_PATH/Manager \ 142 | --method $PD_IFACE.Manager.DeletePrinter \ 143 | "{}" \ 144 | $objpath) 145 | 146 | if [ "$result" != "()" ]; then 147 | printf "Expected (): %s\n" "$result" 148 | result_is 1 149 | fi 150 | 151 | result_is 0 152 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([printerd], 2 | [0.0.1], 3 | [https://github.com/hughsie/printerd/issues], 4 | [printerd]) 5 | 6 | AM_INIT_AUTOMAKE([1.9 no-dist-gzip dist-xz tar-ustar foreign]) 7 | AC_CONFIG_MACRO_DIR([m4]) 8 | AC_CONFIG_SRCDIR([src]) 9 | AC_CONFIG_HEADERS([config.h]) 10 | 11 | AM_MAINTAINER_MODE 12 | 13 | AX_CHECK_ENABLE_DEBUG 14 | AC_PROG_CC 15 | AC_ISC_POSIX 16 | AC_HEADER_STDC 17 | AC_PROG_LIBTOOL 18 | 19 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 20 | 21 | # Initialization 22 | # 23 | 24 | GNOME_COMMON_INIT 25 | GNOME_COMPILE_WARNINGS([maximum]) 26 | GNOME_MAINTAINER_MODE_DEFINES 27 | 28 | AC_PATH_PROG([XSLTPROC], [xsltproc]) 29 | if test -z "$XSLTPROC"; then 30 | AC_MSG_ERROR([xsltproc is needed]) 31 | fi 32 | 33 | GTK_DOC_CHECK([1.3]) 34 | 35 | GOBJECT_INTROSPECTION_CHECK([0.6.2]) 36 | 37 | # Libraries 38 | # 39 | 40 | PKG_CHECK_MODULES(GUDEV, [gudev-1.0 >= 147]) 41 | AC_SUBST(GUDEV_CFLAGS) 42 | AC_SUBST(GUDEV_LIBS) 43 | 44 | PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.30.2]) 45 | AC_SUBST(GLIB_CFLAGS) 46 | AC_SUBST(GLIB_LIBS) 47 | 48 | PKG_CHECK_MODULES(GIO, [gio-unix-2.0 >= 2.30.2]) 49 | AC_SUBST(GIO_CFLAGS) 50 | AC_SUBST(GIO_LIBS) 51 | 52 | PKG_CHECK_MODULES(POLKIT_GOBJECT_1, [polkit-gobject-1 >= 0.92]) 53 | AC_SUBST(POLKIT_GOBJECT_1_CFLAGS) 54 | AC_SUBST(POLKIT_GOBJECT_1_LIBS) 55 | 56 | PKG_CHECK_MODULES(POLKIT_AGENT_1, [polkit-agent-1 >= 0.92]) 57 | AC_SUBST(POLKIT_AGENT_1_CFLAGS) 58 | AC_SUBST(POLKIT_AGENT_1_LIBS) 59 | 60 | AC_PATH_PROG(CUPS_CONFIG, cups-config, no) 61 | if test "x$CUPS_CONFIG" = xno; then 62 | AC_MSG_ERROR([Please install cups development package]) 63 | fi 64 | CUPS_CFLAGS="`$CUPS_CONFIG --cflags`" 65 | CUPS_LIBS="`$CUPS_CONFIG --libs`" 66 | AC_SUBST(CUPS_CFLAGS) 67 | AC_SUBST(CUPS_LIBS) 68 | 69 | # systemd 70 | AC_ARG_ENABLE(systemd, 71 | AS_HELP_STRING([--enable-systemd],[enable systemd [default=yes]]), 72 | enable_systemd=$enableval,enable_systemd=yes) 73 | AM_CONDITIONAL(HAVE_SYSTEMD, test x$enable_systemd = xyes) 74 | if test x$enable_systemd = xyes; then 75 | PKG_CHECK_MODULES(SYSTEMD, 76 | [libsystemd >= 200]) 77 | AC_ARG_WITH([systemdsystemunitdir], 78 | AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]), 79 | [], 80 | [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)]) 81 | if test "x$with_systemdsystemunitdir" != "xno"; then 82 | AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir]) 83 | fi 84 | AC_DEFINE(HAVE_SYSTEMD, 1, [if we should use systemd]) 85 | else 86 | SYSTEMD_CFLAGS="" 87 | SYSTEMD_LIBS="" 88 | fi 89 | AC_SUBST(SYSTEMD_CFLAGS) 90 | AC_SUBST(SYSTEMD_LIBS) 91 | 92 | # Internationalization 93 | # 94 | 95 | IT_PROG_INTLTOOL([$INTLTOOL_REQUIRED]) 96 | GETTEXT_PACKAGE=printerd 97 | AC_SUBST([GETTEXT_PACKAGE]) 98 | AM_GLIB_GNU_GETTEXT 99 | AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[gettext domain]) 100 | ALL_LINGUAS="en_GB en_US es fr id pt_BR pt tr uk vi" 101 | 102 | # Generate 103 | # 104 | 105 | AC_OUTPUT([ 106 | Makefile 107 | data/Makefile 108 | printerd/Makefile 109 | ippd/Makefile 110 | printerd/printerd.pc 111 | src/Makefile 112 | tools/Makefile 113 | doc/Makefile 114 | doc/version.xml 115 | doc/man/Makefile 116 | po/Makefile.in 117 | contrib/printerd.spec 118 | ]) 119 | 120 | dnl ========================================================================== 121 | echo " 122 | printerd $VERSION 123 | ================ 124 | 125 | prefix: ${prefix} 126 | libdir: ${libdir} 127 | libexecdir: ${libexecdir} 128 | bindir: ${bindir} 129 | sbindir: ${sbindir} 130 | datadir: ${datadir} 131 | sysconfdir: ${sysconfdir} 132 | localstatedir: ${localstatedir} 133 | docdir: ${docdir} 134 | introspection: ${found_introspection} 135 | systemdsystemunitdir: ${systemdsystemunitdir} 136 | 137 | compiler: ${CC} 138 | cflags: ${CFLAGS} 139 | cppflags: ${CPPFLAGS} 140 | 141 | Maintainer mode: ${USE_MAINTAINER_MODE} 142 | Building api docs: ${enable_gtk_doc} 143 | " 144 | -------------------------------------------------------------------------------- /tests/common.sh: -------------------------------------------------------------------------------- 1 | [ -n "$VERBOSE" ] && set -x 2 | top_builddir=`cd ${top_builddir-.}; pwd` 3 | PRINTERD="${top_builddir}/src/printerd" 4 | PDCLI="${top_builddir}/tools/pd-cli" 5 | PRINTERD_SESSION_BUS="${top_builddir}"/printerd-session.bus 6 | PYTHON="${PYTHON-python}" 7 | if [ -r "${PRINTERD_SESSION_BUS}" ]; then 8 | DBUS_SESSION_BUS_ADDRESS="$(cat "${PRINTERD_SESSION_BUS}")" 9 | export DBUS_SESSION_BUS_ADDRESS 10 | fi 11 | unset PRINTERD_SESSION_BUS 12 | PD_DEST=org.freedesktop.printerd 13 | PD_PATH=/org/freedesktop/printerd 14 | PD_IFACE=org.freedesktop.printerd 15 | 16 | BOOKMARK="${BOOKMARK-"${top_builddir}/printerd-session.lines-before-test"}" 17 | SESSION_LOG="${SESSION_LOG-"${top_builddir}"/printerd-session.log}" 18 | # Call this function to report test results 19 | result_is () { 20 | n=$(cat "${BOOKMARK}") 21 | if [ "$1" -eq 0 ]; then 22 | if grep -q '\*\*' \ 23 | <(sed -e "1,${n}d" "${SESSION_LOG}"); then 24 | printf "Warnings/errors in output:\n" 25 | sed -e "1,${n}d" "${SESSION_LOG}" 26 | exit 1 27 | fi 28 | else 29 | printf "printerd output:\n" 30 | sed -e "1,${n}d" "${SESSION_LOG}" 31 | fi 32 | exit "$1" 33 | } 34 | 35 | # Remember where we're up to in printerd's output 36 | wc -l < "${SESSION_LOG}" > "${BOOKMARK}" 37 | 38 | simple_ppd () { 39 | tmp="$(mktemp /tmp/printerd.XXXXXXXXXX)" 40 | # Create a simple PPD. 41 | CUPSRASTER="application/vnd.cups-raster 0 -" 42 | cat <<"EOF" | sed -e "s,@CUPSFILTER@,${1-${CUPSRASTER}}," >"$tmp" 43 | *PPD-Adobe: "4.3" 44 | *FormatVersion: "4.3" 45 | *FileVersion: "1.1" 46 | *LanguageVersion: English 47 | *LanguageEncoding: ISOLatin1 48 | *PCFileName: "CUPSFILTER.PPD" 49 | *Manufacturer: "Generic" 50 | *Product: "(Generic Printer)" 51 | *cupsFilter: "@CUPSFILTER@" 52 | *ModelName: "Generic Printer" 53 | *ShortNickName: "Generic Printer" 54 | *NickName: "Generic Printer" 55 | *PSVersion: "(2017.000) 0" 56 | *LanguageLevel: "2" 57 | *ColorDevice: True 58 | *DefaultColorSpace: RGB 59 | *FileSystem: False 60 | *Throughput: "1" 61 | *LandscapeOrientation: Plus90 62 | *VariablePaperSize: False 63 | *TTRasterizer: Type42 64 | *HWMargins: "9 9 9 9" 65 | 66 | *OpenUI *PageSize/Page Size: PickOne 67 | *OrderDependency: 10 AnySetup *PageSize 68 | *DefaultPageSize: Letter 69 | *PageSize Letter/Letter: "<>setpagedevice" 70 | *PageSize Legal/Legal: "<>setpagedevice" 71 | *PageSize A4/A4: "<>setpagedevice" 72 | *CloseUI: *PageSize 73 | 74 | *OpenUI *PageRegion/Page Size: PickOne 75 | *OrderDependency: 10 AnySetup *PageRegion 76 | *DefaultPageRegion: Letter 77 | *PageRegion Letter/Letter: "<>setpagedevice" 78 | *PageRegion A4/A4: "<>setpagedevice" 79 | *PageRegion Legal/Legal: "<>setpagedevice" 80 | *CloseUI: *PageRegion 81 | 82 | *DefaultImageableArea: Letter 83 | *ImageableArea Letter/US Letter: "9 9 594 756" 84 | *ImageableArea A4/A4: "9 9 586.28 833" 85 | *ImageableArea Legal/Legal: "9 9 594 999" 86 | 87 | *DefaultPaperDimension: Letter 88 | *PaperDimension Letter/US Letter: "612 792" 89 | *PaperDimension A4/A4: "595 842" 90 | *PaperDimension Legal/Legal: "612 1008" 91 | EOF 92 | printf "%s" "$tmp" 93 | } 94 | 95 | sample_pdf () { 96 | tmp="$(mktemp /tmp/printerd.XXXXXXXXXX)" 97 | # Create a PDF to print. 98 | # This comes from: /usr/lib/cups/filter/texttopdf 1 test '' 1 '' 99 | # from cups-filters-1.0.58 100 | cat >"$tmp" <<"EOF" 101 | %PDF-1.3 102 | %cupsRotation: 0 103 | 3 0 obj 104 | <> 106 | stream 107 | q 108 | 0 g 109 | BT 110 | 18 745.884 Td 111 | 105.882 Tz 112 | /FN00 11.333 Tf <74657374> Tj 113 | ET 114 | Q 115 | endstream 116 | endobj 117 | 4 0 obj 118 | 75 119 | endobj 120 | 5 0 obj 121 | <> 126 | >> 127 | endobj 128 | 6 0 obj 129 | <> 133 | endobj 134 | 7 0 obj 135 | <> 139 | endobj 140 | 2 0 obj 141 | << 142 | /FB00 6 0 R 143 | /FN00 7 0 R 144 | >> 145 | endobj 146 | 1 0 obj 147 | <> 151 | endobj 152 | 8 0 obj 153 | <> 156 | endobj 157 | 9 0 obj 158 | << 159 | /Creator (texttopdf/1.0.58) 160 | /CreationDate (D:20141130012337+00'00') 161 | /Title () 162 | /Author (test) 163 | >> 164 | endobj 165 | xref 166 | 0 10 167 | 0000000000 65535 f 168 | 0000000486 00000 n 169 | 0000000437 00000 n 170 | 0000000026 00000 n 171 | 0000000152 00000 n 172 | 0000000170 00000 n 173 | 0000000292 00000 n 174 | 0000000367 00000 n 175 | 0000000546 00000 n 176 | 0000000595 00000 n 177 | trailer 178 | << 179 | /Size 10 180 | /Root 8 0 R 181 | /Info 9 0 R 182 | >> 183 | startxref 184 | 717 185 | %%EOF 186 | EOF 187 | printf "%s" "$tmp" 188 | } 189 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | SUBDIRS = \ 4 | doc \ 5 | printerd \ 6 | ippd \ 7 | data \ 8 | src \ 9 | tools \ 10 | po 11 | 12 | run-pd-view: 13 | GI_TYPELIB_PATH=$(top_builddir)/printerd \ 14 | LD_LIBRARY_PATH=$(top_builddir)/printerd/.libs:$$LD_LIBRARY_PATH \ 15 | DBUS_SESSION_BUS_ADDRESS=$$(cat printerd-session.bus) \ 16 | PD_USE_SESSION_BUS=1 \ 17 | $(PYTHON3) $(top_srcdir)/tools/pd-view.py 18 | 19 | run-ippd: printerd-session.pid 20 | GI_TYPELIB_PATH=$(top_builddir)/printerd \ 21 | LD_LIBRARY_PATH=$(top_builddir)/printerd/.libs:$$LD_LIBRARY_PATH \ 22 | DBUS_SESSION_BUS_ADDRESS=$$(cat printerd-session.bus) \ 23 | PD_USE_SESSION_BUS=1 \ 24 | $(PYTHON3) $(top_srcdir)/ippd/ippd.py 25 | 26 | stop-session-service: 27 | if [ -e printerd-session.pid ]; then \ 28 | tests/stop-session-service/run-test; \ 29 | fi 30 | 31 | # Regression tests 32 | PYTHON=python 33 | PYTHON3=python3 34 | TEST_BOOKMARK=$(top_builddir)/printerd-session.lines-before-test 35 | TEST_SESSION_LOG=$(top_builddir)/printerd-session.log 36 | TESTS_ENVIRONMENT = \ 37 | top_srcdir=$(top_srcdir) \ 38 | top_builddir=$(top_builddir) \ 39 | PYTHON=$(PYTHON) \ 40 | BOOKMARK=$(TEST_BOOKMARK) \ 41 | SESSION_LOG=$(TEST_SESSION_LOG) 42 | 43 | # A rule to start printerd on a session bus of its own 44 | printerd-session.pid: all 45 | bash $(top_srcdir)/tests/start-session-service.sh 46 | 47 | # A rule to make the test scripts executable 48 | tests/started/run-test: 49 | for test in $(TESTS); do \ 50 | chmod a+x $(top_srcdir)/$$test; \ 51 | done 52 | 53 | ALL_INTROSPECTION_TESTS = \ 54 | tests/python1/run-test 55 | 56 | if HAVE_INTROSPECTION 57 | INTROSPECTION_TESTS = $(ALL_INTROSPECTION_TESTS) 58 | else 59 | INTROSPECTION_TESTS = 60 | endif 61 | 62 | # Here's where most of the tests go. 63 | AFTER_GETPRINTERS_TESTS = \ 64 | tests/createprinter1/run-test \ 65 | tests/createprinter2/run-test \ 66 | tests/createprinter3/run-test \ 67 | tests/createprinter5/run-test \ 68 | tests/updatedriver1/run-test \ 69 | tests/job1/run-test \ 70 | tests/job2/run-test \ 71 | tests/job3/run-test \ 72 | tests/job4/run-test \ 73 | tests/filter1/run-test \ 74 | tests/filter2/run-test \ 75 | $(INTROSPECTION_TESTS) 76 | 77 | # Some tests have to run at the beginning. 78 | ALL_TESTS = \ 79 | tests/started/run-test \ 80 | tests/version/run-test \ 81 | tests/Manager.GetPrinters/run-test \ 82 | $(AFTER_GETPRINTERS_TESTS) 83 | 84 | # One test has to run at the end. 85 | STOP_TESTS = \ 86 | tests/stop-session-service/run-test 87 | 88 | TESTS = \ 89 | $(ALL_TESTS) \ 90 | $(STOP_TESTS) 91 | 92 | # Some tests are known to fail at the moment. 93 | XFAIL_TESTS = \ 94 | tests/createprinter3/run-test 95 | 96 | # Start the session daemon before running the tests 97 | $(TESTS:run-test=run-test.log): printerd-session.pid 98 | 99 | # Make sure Mananger.GetPrinters is tested before other failed tests 100 | # can leave printers lying around. 101 | $(AFTER_GETPRINTERS_TESTS:run-test=run-test.log): tests/Manager.GetPrinters/run-test.log 102 | 103 | # Don't run the stop-session-service test until all others have finished. 104 | $(STOP_TESTS:run-test=run-test.log): $(ALL_TESTS:run-test=run-test.log) 105 | 106 | DISTCLEANFILES = \ 107 | $(TEST_SESSION_LOG) \ 108 | $(TEST_BOOKMARK) \ 109 | printerd-session.pid \ 110 | printerd-session.bus 111 | 112 | MAINTAINERCLEANFILES = \ 113 | $(srcdir)/INSTALL \ 114 | $(srcdir)/ABOUT-NLS \ 115 | $(srcdir)/aclocal.m4 \ 116 | $(srcdir)/autoscan.log \ 117 | $(srcdir)/compile \ 118 | $(srcdir)/config.guess \ 119 | $(srcdir)/config.rpath \ 120 | $(srcdir)/config.h.in \ 121 | $(srcdir)/config.sub \ 122 | $(srcdir)/configure.scan \ 123 | $(srcdir)/depcomp \ 124 | $(srcdir)/install-sh \ 125 | $(srcdir)/ltmain.sh \ 126 | $(srcdir)/missing \ 127 | $(srcdir)/mkinstalldirs \ 128 | $(srcdir)/omf.make \ 129 | $(srcdir)/xmldocs.make \ 130 | $(srcdir)/gtk-doc.make \ 131 | $(srcdir)/ChangeLog \ 132 | $(srcdir)/po/Makefile.in.in~ \ 133 | $(srcdir)/printerd-*.tar.* \ 134 | `find "$(srcdir)" -type f -name Makefile.in -print` 135 | 136 | DISTCHECK_CONFIGURE_FLAGS = \ 137 | --disable-introspection \ 138 | --with-systemdsystemunitdir= 139 | 140 | distclean-local: 141 | if test $(srcdir) = .; then :; else \ 142 | rm -f ChangeLog; \ 143 | fi 144 | 145 | ChangeLog: 146 | @echo Creating $@ 147 | @if test -d "$(srcdir)/.git"; then \ 148 | (GIT_DIR=$(top_srcdir)/.git ./missing --run git log --stat -M -C --name-status --date=short --no-color) | fmt --split-only > $@.tmp \ 149 | && mv -f $@.tmp $@ \ 150 | || ($(RM) $@.tmp; \ 151 | echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ 152 | (test -f $@ || echo git-log is required to generate this file >> $@)); \ 153 | else \ 154 | test -f $@ || \ 155 | (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ 156 | echo A git checkout and git-log is required to generate this file >> $@); \ 157 | fi 158 | 159 | .PHONY: ChangeLog 160 | 161 | EXTRA_DIST = \ 162 | tests/common.sh tests/start-session-service.sh \ 163 | $(TESTS) $(XFAIL_TESTS) \ 164 | $(INTROSPECTION_TESTS) \ 165 | tests/python1/Manager.GetPrinters.py \ 166 | README.md TESTS.md \ 167 | contrib/printerd.spec \ 168 | ippd/ippd.py 169 | 170 | -include $(top_srcdir)/git.mk 171 | -------------------------------------------------------------------------------- /src/pd-log.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012, 2014 Tim Waugh 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #ifndef __PD_LOG_H__ 22 | #define __PD_LOG_H__ 23 | 24 | #ifdef HAVE_SYSTEMD 25 | # include 26 | #else 27 | # include 28 | #endif /* HAVE_SYSTEMD */ 29 | 30 | G_BEGIN_DECLS 31 | 32 | #ifdef HAVE_SYSTEMD 33 | # define printer_log(printer,priority,g_,msg,args...) \ 34 | do { \ 35 | const gchar *_name = pd_printer_get_name (PD_PRINTER (printer)); \ 36 | sd_journal_send("MESSAGE=[Printer %s] " msg, _name, ##args, \ 37 | "PRIORITY=%i", priority, \ 38 | "PRINTERD_PRINTER=%s", _name, \ 39 | NULL); \ 40 | g_("[Printer %s] " msg, _name, ##args); \ 41 | } while (0) 42 | 43 | # define job_log(job,priority,g_,msg,args...) \ 44 | do { \ 45 | guint _id = pd_job_get_id (PD_JOB (job)); \ 46 | const gchar *_path = pd_job_get_printer (PD_JOB (job)); \ 47 | PdDaemon *_daemon = pd_job_impl_get_daemon (PD_JOB_IMPL (job)); \ 48 | PdObject *_obj = pd_daemon_find_object (_daemon, \ 49 | _path); \ 50 | PdPrinter *_printer = NULL; \ 51 | const gchar *_name = NULL; \ 52 | if (_obj) { \ 53 | _printer = pd_object_get_printer (_obj); \ 54 | _name = pd_printer_get_name (PD_PRINTER (_printer)); \ 55 | } \ 56 | sd_journal_send("MESSAGE=[Job %u] " msg, _id, ##args, \ 57 | "PRIORITY=%i", priority, \ 58 | "PRINTERD_JOB_ID=%u", _id, \ 59 | _name ? "PRINTERD_PRINTER=%s" : NULL, _name, \ 60 | NULL); \ 61 | if (_obj) \ 62 | g_object_unref (_obj); \ 63 | if (_printer) \ 64 | g_object_unref (_printer); \ 65 | g_("[Job %u] " msg, _id, ##args); \ 66 | } while (0) 67 | 68 | # define manager_log(manager,priority,g_,msg,args...) \ 69 | do { \ 70 | sd_journal_send("MESSAGE=[Manager] " msg, ##args, \ 71 | "PRIORITY=%i", priority, \ 72 | NULL); \ 73 | g_("[Manager] " msg, ##args); \ 74 | } while (0) 75 | 76 | # define engine_log(engine,priority,g_,msg,args...) \ 77 | do { \ 78 | sd_journal_send("MESSAGE=[Engine] " msg, ##args, \ 79 | "PRIORITY=%i", priority, \ 80 | NULL); \ 81 | g_("[Engine] " msg, ##args); \ 82 | } while (0) 83 | 84 | #else /* !defined(HAVE_SYSTEMD) */ 85 | 86 | # define printer_log(printer,priority,g_,msg,args...) \ 87 | do { \ 88 | const gchar *_name = pd_printer_get_name (PD_PRINTER (printer)); \ 89 | syslog(priority, "[Printer %s] " msg, _name, ##args); \ 90 | g_("[Printer %s] " msg, _name, ##args); \ 91 | } while (0) 92 | 93 | # define job_log(job,priority,g_,msg,args...) \ 94 | do { \ 95 | guint _id = pd_job_get_id (PD_JOB (job)); \ 96 | syslog(priority, "[Job %u] " msg, _id, ##args); \ 97 | g_("[Job %u] " msg, _id, ##args); \ 98 | } while (0) 99 | 100 | # define manager_log(manager,priority,g_,msg,args...) \ 101 | do { \ 102 | syslog(priority, "[Manager] " msg, ##args); \ 103 | g_("[Manager] " msg, ##args); \ 104 | } while (0); 105 | 106 | #define engine_log(engine,priority,g_,msg,args...) \ 107 | do { \ 108 | syslog(priority, "[Engine] " msg, ##args); \ 109 | g_("[Engine] " msg, ##args); \ 110 | } while (0); 111 | 112 | #endif /* defined(HAVE_SYSTEMD) */ 113 | 114 | #define printer_debug(printer,msg,args...) \ 115 | printer_log(printer,LOG_DEBUG,g_debug,msg,##args) 116 | 117 | #define printer_warning(printer,msg,args...) \ 118 | printer_log(printer,LOG_WARNING,g_warning,msg,##args) 119 | 120 | #define printer_error(printer,msg,args...) \ 121 | printer_log(printer,LOG_ERR,g_warning,msg,##args) 122 | 123 | 124 | #define job_debug(job,msg,args...) \ 125 | job_log(job,LOG_DEBUG,g_debug,msg,##args) 126 | 127 | #define job_warning(job,msg,args...) \ 128 | job_log(job,LOG_WARNING,g_warning,msg,##args) 129 | 130 | #define job_error(job,msg,args...) \ 131 | job_log(job,LOG_ERR,g_warning,msg,##args) 132 | 133 | #define manager_debug(manager,msg,args...) \ 134 | manager_log(manager,LOG_DEBUG,g_debug,msg,##args) 135 | 136 | #define manager_warning(manager,msg,args...) \ 137 | manager_log(manager,LOG_WARNING,g_warning,msg,##args) 138 | 139 | #define manager_error(manager,msg,args...) \ 140 | manager_log(manager,LOG_ERR,g_warning,msg,##args) 141 | 142 | #define engine_debug(engine,msg,args...) \ 143 | engine_log(engine,LOG_DEBUG,g_debug,msg,##args) 144 | 145 | #define engine_warning(engine,msg,args...) \ 146 | engine_log(engine,LOG_WARNING,g_warning,msg,##args) 147 | 148 | #define engine_error(engine,msg,args...) \ 149 | engine_log(engine,LOG_ERR,g_warning,msg,##args) 150 | 151 | 152 | G_END_DECLS 153 | 154 | #endif /* __PD_LOG_H__ */ 155 | -------------------------------------------------------------------------------- /printerd/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | AM_CPPFLAGS = \ 3 | -I$(top_builddir) -I$(top_srcdir) \ 4 | -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ 5 | -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ 6 | -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ 7 | -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ 8 | -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ 9 | -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ 10 | -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ 11 | -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ 12 | -DPRINTERD_COMPILATION \ 13 | $(GLIB_CFLAGS) \ 14 | $(GIO_CFLAGS) \ 15 | $(WARN_CFLAGS) \ 16 | $(NULL) 17 | 18 | $(dbus_built_sources): .stamp-dbus-built-sources 19 | 20 | .stamp-dbus-built-sources: Makefile.am $(top_srcdir)/data/org.freedesktop.printerd.xml 21 | gdbus-codegen \ 22 | --interface-prefix org.freedesktop.printerd. \ 23 | --c-namespace Pd \ 24 | --c-generate-object-manager \ 25 | --generate-c-code pd-generated \ 26 | --generate-docbook pd-generated-doc \ 27 | $(top_srcdir)/data/org.freedesktop.printerd.xml \ 28 | $(NULL) 29 | @touch $@ 30 | 31 | pd-enumtypes.h: pd-enums.h pd-enumtypes.h.template 32 | ( top_builddir=`cd $(top_builddir) && pwd`; \ 33 | cd $(srcdir) && glib-mkenums --template pd-enumtypes.h.template pd-enums.h ) > \ 34 | pd-enumtypes.h.tmp && mv pd-enumtypes.h.tmp pd-enumtypes.h 35 | 36 | pd-enumtypes.c: pd-enums.h pd-enumtypes.c.template 37 | ( top_builddir=`cd $(top_builddir) && pwd`; \ 38 | cd $(srcdir) && glib-mkenums --template pd-enumtypes.c.template pd-enums.h ) > \ 39 | pd-enumtypes.c.tmp && mv pd-enumtypes.c.tmp pd-enumtypes.c 40 | 41 | enum_built_sources = \ 42 | pd-enumtypes.h \ 43 | pd-enumtypes.c \ 44 | $(NULL) 45 | 46 | dbus_built_sources = \ 47 | pd-generated.h \ 48 | pd-generated.c \ 49 | $(NULL) 50 | 51 | BUILT_SOURCES = \ 52 | $(enum_built_sources) \ 53 | $(dbus_built_sources) \ 54 | $(NULL) 55 | 56 | lib_LTLIBRARIES = libprinterd.la 57 | 58 | libprinterdincludedir=$(includedir)/printerd/printerd 59 | 60 | libprinterdinclude_HEADERS= \ 61 | printerd.h \ 62 | pd-client.h \ 63 | pd-enums.h \ 64 | pd-enumtypes.h \ 65 | pd-error.h \ 66 | pd-types.h \ 67 | pd-generated.h \ 68 | $(NULL) 69 | 70 | libprinterd_la_SOURCES = \ 71 | $(BUILT_SOURCES) \ 72 | pd-client.h \ 73 | pd-client.c \ 74 | pd-enums.h \ 75 | pd-error.h \ 76 | pd-error.c \ 77 | pd-types.h \ 78 | $(NULL) 79 | 80 | libprinterd_la_CFLAGS = \ 81 | -DG_LOG_DOMAIN=\"libprinterd\" \ 82 | $(GLIB_CFLAGS) \ 83 | $(GIO_CFLAGS) \ 84 | $(NULL) 85 | 86 | libprinterd_la_LIBADD = \ 87 | $(GLIB_LIBS) \ 88 | $(GIO_LIBS) \ 89 | $(NULL) 90 | 91 | # ---------------------------------------------------------------------- 92 | 93 | pkgconfigdir = $(libdir)/pkgconfig 94 | pkgconfig_DATA = printerd.pc 95 | 96 | # ---------------------------------------------------------------------- 97 | 98 | if HAVE_INTROSPECTION 99 | 100 | INTROSPECTION_GIRS = printerd-1.0.gir 101 | 102 | girdir = $(INTROSPECTION_GIRDIR) 103 | gir_DATA = printerd-1.0.gir 104 | 105 | typelibsdir = $(INTROSPECTION_TYPELIBDIR) 106 | typelibs_DATA = printerd-1.0.typelib 107 | 108 | printerd_1_0_gir_SCANNERFLAGS = \ 109 | --c-include='printerd/printerd.h' \ 110 | --warn-all \ 111 | --namespace printerd \ 112 | --identifier-prefix Pd \ 113 | --symbol-prefix pd \ 114 | --warn-all \ 115 | $(NULL) 116 | 117 | printerd_1_0_gir_CFLAGS = \ 118 | $(libprinterd_la_CFLAGS) \ 119 | -DPRINTERD_COMPILATION \ 120 | -I$(top_srcdir) \ 121 | -I$(top_builddir) \ 122 | $(NULL) 123 | 124 | printerd-1.0.gir: libprinterd.la 125 | printerd_1_0_gir_INCLUDES = Gio-2.0 126 | printerd_1_0_gir_LIBS = libprinterd.la 127 | printerd_1_0_gir_FILES = $(libprinterd_la_SOURCES) 128 | printerd_1_0_gir_EXPORT_PACKAGES = printerd 129 | 130 | include $(INTROSPECTION_MAKEFILE) 131 | 132 | .stamp-fix-up-generated: $(libprinterd_la_SOURCES) 133 | @echo " Working around GNOME bug #741167" 134 | @sed -i -e 's,\(out_\(printers\|devices\|drivers\): (out)\):,\1 (array zero-terminated=1):,' pd-generated.c 135 | @touch $@ 136 | 137 | printerd-1.0.gir: $(printerd_1_0_gir_FILES) .stamp-fix-up-generated 138 | $(_gir_silent_scanner_prefix) $(INTROSPECTION_SCANNER_ENV) $(INTROSPECTION_SCANNER) $(_gir_silent_scanner_opts) \ 139 | $(INTROSPECTION_SCANNER_ARGS) \ 140 | --namespace=$(_gir_namespace) \ 141 | --nsversion=$(_gir_version) \ 142 | $(_gir_libtool) \ 143 | --include=Gio-2.0 \ 144 | --pkg-export=printerd \ 145 | --library=libprinterd.la \ 146 | $(printerd_1_0_gir_SCANNERFLAGS) \ 147 | --cflags-begin \ 148 | $(printerd_1_0_gir_CFLAGS) \ 149 | --cflags-end \ 150 | $(printerd_1_0_gir_LDFLAGS) \ 151 | $^ \ 152 | --output $@ 153 | 154 | endif # HAVE_INTROSPECTION 155 | 156 | # ---------------------------------------------------------------------- 157 | 158 | CLEANFILES = pd-generated-doc-*.xml pd-generated.[ch] $(gir_DATA) $(typelibs_DATA) 159 | 160 | EXTRA_DIST = \ 161 | printerd.pc.in \ 162 | pd-enumtypes.h.template \ 163 | pd-enumtypes.c.template \ 164 | $(NULL) 165 | 166 | dist-hook : 167 | (for i in $(BUILT_SOURCES) ; do rm -f $(distdir)/$$i ; done) 168 | 169 | clean-local : 170 | rm -f *~ $(BUILT_SOURCES) .stamp-fix-up-generated .stamp-dbus-built-sources 171 | 172 | -include $(top_srcdir)/git.mk 173 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-file-style: "gnu" -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #include "config.h" 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include "pd-daemontypes.h" 29 | #include "pd-daemon.h" 30 | 31 | static gboolean opt_no_sigint = FALSE; 32 | static gboolean opt_replace = FALSE; 33 | static gboolean opt_session = FALSE; 34 | static GMainLoop *loop = NULL; 35 | static PdDaemon *the_daemon = NULL; 36 | 37 | static void 38 | on_bus_acquired (GDBusConnection *connection, 39 | const gchar *name, 40 | gpointer user_data) 41 | { 42 | the_daemon = pd_daemon_new (connection, opt_session); 43 | g_debug ("Connected to the %s bus", opt_session ? "session" : "system"); 44 | } 45 | 46 | static void 47 | on_name_lost (GDBusConnection *connection, 48 | const gchar *name, 49 | gpointer user_data) 50 | { 51 | if (the_daemon == NULL) 52 | g_error ("Failed to connect to the %s message bus", 53 | opt_session ? "session" : "system"); 54 | else 55 | g_debug ("Lost (or failed to acquire) the name %s on the " 56 | "%s message bus", 57 | name, opt_session ? "session" : "system"); 58 | g_main_loop_quit (loop); 59 | } 60 | 61 | static void 62 | on_name_acquired (GDBusConnection *connection, 63 | const gchar *name, 64 | gpointer user_data) 65 | { 66 | g_debug ("Acquired the name %s on the %s message bus", name, 67 | opt_session ? "session" : "system"); 68 | } 69 | 70 | static gboolean 71 | on_sigint (gpointer user_data) 72 | { 73 | g_debug ("Caught SIGINT. Initiating shutdown"); 74 | g_main_loop_quit (loop); 75 | return G_SOURCE_CONTINUE; 76 | } 77 | 78 | static void 79 | pd_log_ignore_cb (const gchar *log_domain, GLogLevelFlags log_level, 80 | const gchar *message, gpointer user_data) 81 | { 82 | } 83 | 84 | static void 85 | pd_log_handler_cb (const gchar *log_domain, GLogLevelFlags log_level, 86 | const gchar *message, gpointer user_data) 87 | { 88 | gchar str_time[255]; 89 | time_t the_time; 90 | 91 | /* not a console */ 92 | if (isatty (fileno (stdout)) == 0) { 93 | g_print ("%s\n", message); 94 | return; 95 | } 96 | 97 | /* header always in green */ 98 | time (&the_time); 99 | strftime (str_time, 254, "%H:%M:%S", localtime (&the_time)); 100 | g_print ("%c[%dmTI:%s\t", 0x1B, 32, str_time); 101 | 102 | /* critical is also in red */ 103 | if (log_level == G_LOG_LEVEL_CRITICAL || 104 | log_level == G_LOG_LEVEL_WARNING || 105 | log_level == G_LOG_LEVEL_ERROR) { 106 | g_print ("%c[%dm%s\n%c[%dm", 0x1B, 31, message, 0x1B, 0); 107 | } else { 108 | /* debug in blue */ 109 | g_print ("%c[%dm%s\n%c[%dm", 0x1B, 34, message, 0x1B, 0); 110 | } 111 | } 112 | 113 | int 114 | main (int argc, char **argv) 115 | { 116 | GError *error = NULL; 117 | gint ret = 1; 118 | GOptionContext *opt_context = NULL; 119 | guint name_owner_id = 0; 120 | guint sigint_id = 0; 121 | gboolean verbose = FALSE; 122 | GOptionEntry opt_entries[] = { 123 | { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, 124 | _("Show extra debugging information"), NULL }, 125 | { "replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, 126 | "Replace existing daemon", NULL}, 127 | { "no-sigint", 's', 0, G_OPTION_ARG_NONE, &opt_no_sigint, 128 | "Do not handle SIGINT for controlled shutdown", NULL}, 129 | { "session", 'S', 0, G_OPTION_ARG_NONE, &opt_session, 130 | _("Use the session D-Bus (for testing)"), NULL}, 131 | {NULL } 132 | }; 133 | 134 | #if !GLIB_CHECK_VERSION(2,36,0) 135 | g_type_init (); 136 | #endif /* glib < 2.36 */ 137 | 138 | /* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */ 139 | if (!g_setenv ("GIO_USE_VFS", "local", TRUE)) { 140 | g_printerr ("Error setting GIO_USE_GVFS\n"); 141 | goto out; 142 | } 143 | 144 | opt_context = g_option_context_new ("printer daemon"); 145 | g_option_context_add_main_entries (opt_context, opt_entries, NULL); 146 | if (!g_option_context_parse (opt_context, &argc, &argv, &error)) { 147 | g_printerr ("Error parsing options: %s\n", error->message); 148 | g_error_free (error); 149 | goto out; 150 | } 151 | 152 | /* verbose? */ 153 | if (verbose) { 154 | g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); 155 | g_log_set_handler ("printerd", 156 | G_LOG_LEVEL_ERROR | 157 | G_LOG_LEVEL_CRITICAL | 158 | G_LOG_LEVEL_DEBUG | 159 | G_LOG_LEVEL_WARNING, 160 | pd_log_handler_cb, NULL); 161 | } else { 162 | g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); 163 | g_log_set_handler ("printerd", G_LOG_LEVEL_DEBUG, 164 | pd_log_ignore_cb, NULL); 165 | } 166 | 167 | loop = g_main_loop_new (NULL, FALSE); 168 | 169 | if (!opt_no_sigint) { 170 | sigint_id = g_unix_signal_add_full (G_PRIORITY_DEFAULT, 171 | SIGINT, 172 | on_sigint, 173 | NULL, /* user_data */ 174 | NULL); /* GDestroyNotify */ 175 | } 176 | 177 | name_owner_id = g_bus_own_name (opt_session ? 178 | G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM, 179 | "org.freedesktop.printerd", 180 | G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | 181 | (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0), 182 | on_bus_acquired, 183 | on_name_acquired, 184 | on_name_lost, 185 | NULL, 186 | NULL); 187 | g_debug ("Entering main event loop"); 188 | g_main_loop_run (loop); 189 | 190 | /* success */ 191 | ret = 0; 192 | out: 193 | if (sigint_id > 0) 194 | g_source_remove (sigint_id); 195 | if (the_daemon != NULL) 196 | g_object_unref (the_daemon); 197 | if (name_owner_id != 0) 198 | g_bus_unown_name (name_owner_id); 199 | if (loop != NULL) 200 | g_main_loop_unref (loop); 201 | if (opt_context != NULL) 202 | g_option_context_free (opt_context); 203 | g_debug ("printerd daemon version %s exiting", PACKAGE_VERSION); 204 | return ret; 205 | } 206 | -------------------------------------------------------------------------------- /git.mk: -------------------------------------------------------------------------------- 1 | # git.mk 2 | # 3 | # Copyright 2009, Red Hat, Inc. 4 | # Written by Behdad Esfahbod 5 | # 6 | # Copying and distribution of this file, with or without modification, 7 | # are permitted in any medium without royalty provided the copyright 8 | # notice and this notice are preserved. 9 | # 10 | # The canonical source for this file is pango/git.mk, or whereever the 11 | # header of pango/git.mk suggests in the future. 12 | # 13 | # To use in your project, import this file in your git repo's toplevel, 14 | # then do "make -f git.mk". This modifies all Makefile.am files in 15 | # your project to include git.mk. 16 | # 17 | # This enables automatic .gitignore generation. If you need to ignore 18 | # more files, add them to the GITIGNOREFILES variable in your Makefile.am. 19 | # But think twice before doing that. If a file has to be in .gitignore, 20 | # chances are very high that it's a generated file and should be in one 21 | # of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES. 22 | # 23 | # The only case that you need to manually add a file to GITIGNOREFILES is 24 | # when remove files in one of mostlyclean-local, clean-local, distclean-local, 25 | # or maintainer-clean-local. 26 | # 27 | # Note that for files like editor backup, etc, there are better places to 28 | # ignore them. See "man gitignore". 29 | # 30 | # If "make maintainer-clean" removes the files but they are not recognized 31 | # by this script (that is, if "git status" shows untracked files still), send 32 | # me the output of "git status" as well as your Makefile.am and Makefile for 33 | # the directories involved. 34 | # 35 | # For a list of toplevel files that should be in MAINTAINERCLEANFILES, see 36 | # pango/Makefile.am. 37 | # 38 | # Don't EXTRA_DIST this file. It is supposed to only live in git clones, 39 | # not tarballs. It serves no useful purpose in tarballs and clutters the 40 | # build dir. 41 | # 42 | # This file knows how to handle autoconf, automake, libtool, gtk-doc, 43 | # gnome-doc-utils, mallard, intltool, gsettings. 44 | # 45 | # 46 | # KNOWN ISSUES: 47 | # 48 | # - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the 49 | # submodule doesn't find us. If you have configure.{in,ac} files in 50 | # subdirs, add a proxy git.mk file in those dirs that simply does: 51 | # "include $(top_srcdir)/../git.mk". Add more ..'s to your taste. 52 | # And add those files to git. See vte/gnome-pty-helper/git.mk for 53 | # example. 54 | # 55 | # ChangeLog 56 | # 57 | # - 2010-12-06 Add support for Mallard docs 58 | # - 2010-12-06 Start this change log 59 | 60 | git-all: git-mk-install 61 | 62 | git-mk-install: 63 | @echo Installing git makefile 64 | @any_failed=; find $(top_srcdir) -name Makefile.am | while read x; do \ 65 | if grep 'include .*/git.mk' $$x >/dev/null; then \ 66 | echo $$x already includes git.mk; \ 67 | else \ 68 | failed=; \ 69 | echo "Updating $$x"; \ 70 | { cat $$x; \ 71 | echo ''; \ 72 | echo '-include $$(top_srcdir)/git.mk'; \ 73 | } > $$x.tmp || failed=1; \ 74 | if test x$$failed = x; then \ 75 | mv $$x.tmp $$x || failed=1; \ 76 | fi; \ 77 | if test x$$failed = x; then : else \ 78 | echo Failed updating $$x; >&2 \ 79 | any_failed=1; \ 80 | fi; \ 81 | fi; done; test -z "$$any_failed" 82 | 83 | .PHONY: git-all git-mk-install 84 | 85 | 86 | ### .gitignore generation 87 | 88 | $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk 89 | $(AM_V_GEN) \ 90 | { \ 91 | if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \ 92 | for x in \ 93 | $(DOC_MODULE)-decl-list.txt \ 94 | $(DOC_MODULE)-decl.txt \ 95 | tmpl/$(DOC_MODULE)-unused.sgml \ 96 | "tmpl/*.bak" \ 97 | xml html \ 98 | ; do echo /$$x; done; \ 99 | fi; \ 100 | if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \ 101 | for x in \ 102 | $(_DOC_C_DOCS) \ 103 | $(_DOC_LC_DOCS) \ 104 | $(_DOC_OMF_ALL) \ 105 | $(_DOC_DSK_ALL) \ 106 | $(_DOC_HTML_ALL) \ 107 | $(_DOC_MOFILES) \ 108 | $(_DOC_POFILES) \ 109 | $(DOC_H_FILE) \ 110 | "*/.xml2po.mo" \ 111 | "*/*.omf.out" \ 112 | ; do echo /$$x; done; \ 113 | fi; \ 114 | if test "x$(gsettings_SCHEMAS)" = x; then :; else \ 115 | for x in \ 116 | $(gsettings_SCHEMAS:.xml=.valid) \ 117 | $(gsettings__enum_file) \ 118 | ; do echo /$$x; done; \ 119 | fi; \ 120 | if test -f $(srcdir)/po/Makefile.in.in; then \ 121 | for x in \ 122 | po/Makefile.in.in \ 123 | po/Makefile.in \ 124 | po/Makefile \ 125 | po/POTFILES \ 126 | po/stamp-it \ 127 | po/.intltool-merge-cache \ 128 | "po/*.gmo" \ 129 | "po/*.mo" \ 130 | po/$(GETTEXT_PACKAGE).pot \ 131 | intltool-extract.in \ 132 | intltool-merge.in \ 133 | intltool-update.in \ 134 | ; do echo /$$x; done; \ 135 | fi; \ 136 | if test -f $(srcdir)/configure; then \ 137 | for x in \ 138 | autom4te.cache \ 139 | configure \ 140 | config.h \ 141 | stamp-h1 \ 142 | libtool \ 143 | config.lt \ 144 | ; do echo /$$x; done; \ 145 | fi; \ 146 | for x in \ 147 | .gitignore \ 148 | $(GITIGNOREFILES) \ 149 | $(CLEANFILES) \ 150 | $(PROGRAMS) \ 151 | $(check_PROGRAMS) \ 152 | $(EXTRA_PROGRAMS) \ 153 | $(LTLIBRARIES) \ 154 | so_locations \ 155 | .libs _libs \ 156 | $(MOSTLYCLEANFILES) \ 157 | "*.$(OBJEXT)" \ 158 | "*.lo" \ 159 | $(DISTCLEANFILES) \ 160 | $(am__CONFIG_DISTCLEAN_FILES) \ 161 | $(CONFIG_CLEAN_FILES) \ 162 | TAGS ID GTAGS GRTAGS GSYMS GPATH tags \ 163 | "*.tab.c" \ 164 | $(MAINTAINERCLEANFILES) \ 165 | $(BUILT_SOURCES) \ 166 | $(DEPDIR) \ 167 | Makefile \ 168 | Makefile.in \ 169 | "*.orig" \ 170 | "*.rej" \ 171 | "*.bak" \ 172 | "*~" \ 173 | ".*.sw[nop]" \ 174 | ".dirstamp" \ 175 | ; do echo /$$x; done; \ 176 | } | \ 177 | sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \ 178 | sed 's@/[.]/@/@g' | \ 179 | LC_ALL=C sort | uniq > $@.tmp && \ 180 | mv $@.tmp $@; 181 | 182 | all: $(srcdir)/.gitignore gitignore-recurse-maybe 183 | gitignore-recurse-maybe: 184 | @if test "x$(SUBDIRS)" = "x$(DIST_SUBDIRS)"; then :; else \ 185 | $(MAKE) $(AM_MAKEFLAGS) gitignore-recurse; \ 186 | fi; 187 | gitignore-recurse: 188 | @for subdir in $(DIST_SUBDIRS); do \ 189 | case " $(SUBDIRS) " in \ 190 | *" $$subdir "*) :;; \ 191 | *) test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) .gitignore gitignore-recurse || echo "Skipping $$subdir");; \ 192 | esac; \ 193 | done 194 | gitignore: $(srcdir)/.gitignore gitignore-recurse 195 | 196 | maintainer-clean: gitignore-clean 197 | gitignore-clean: 198 | -rm -f $(srcdir)/.gitignore 199 | 200 | .PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe 201 | -------------------------------------------------------------------------------- /src/pd-common.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012, 2014 Tim Waugh 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #include "config.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include "pd-common.h" 31 | #include "pd-job-impl.h" 32 | #include "pd-printer-impl.h" 33 | 34 | GHashTable * 35 | pd_parse_ieee1284_id (const gchar *idstring) 36 | { 37 | GHashTable *fields; 38 | gchar **fvs; 39 | gchar **each; 40 | 41 | g_return_val_if_fail (idstring, NULL); 42 | 43 | fields = g_hash_table_new_full (g_str_hash, 44 | g_str_equal, 45 | g_free, 46 | g_free); 47 | 48 | fvs = g_strsplit (idstring, ";", 0); 49 | 50 | /* parse the IEEE 1284 Device ID */ 51 | for (each = fvs; *each; each++) { 52 | gchar *fieldname; 53 | gchar **fv = g_strsplit (*each, ":", 2); 54 | if (fv[0] == NULL || fv[1] == NULL) { 55 | g_strfreev (fv); 56 | continue; 57 | } 58 | 59 | g_strstrip (fv[0]); 60 | g_strstrip (fv[1]); 61 | if (!g_ascii_strcasecmp (fv[0], "mfg") || 62 | !g_ascii_strcasecmp (fv[0], "manufacturer")) { 63 | fieldname = g_strdup ("mfg"); 64 | } else if (!g_ascii_strcasecmp (fv[0], "mdl") || 65 | !g_ascii_strcasecmp (fv[0], "model")) { 66 | fieldname = g_strdup ("mdl"); 67 | } else if (!g_ascii_strcasecmp (fv[0], "des") || 68 | !g_ascii_strcasecmp (fv[0], "description")) { 69 | fieldname = g_strdup ("des"); 70 | } else 71 | fieldname = g_ascii_strdown (fv[0], -1); 72 | 73 | g_hash_table_insert (fields, fieldname, g_strdup (fv[1])); 74 | g_strfreev (fv); 75 | } 76 | 77 | g_strfreev (fvs); 78 | return fields; 79 | } 80 | 81 | const gchar * 82 | pd_job_state_as_string (guint job_state) 83 | { 84 | static const gchar *text[] = { 85 | "pending", 86 | "pending-held", 87 | "processing", 88 | "processing-stopped", 89 | "canceled", 90 | "aborted", 91 | "completed" 92 | }; 93 | 94 | if (job_state < PD_JOB_STATE_PENDING || 95 | job_state - 3 > sizeof (text)) 96 | return "unknown"; 97 | 98 | return text[job_state - PD_JOB_STATE_PENDING]; 99 | } 100 | 101 | const gchar * 102 | pd_printer_state_as_string (guint printer_state) 103 | { 104 | static const gchar *text[] = { 105 | "idle", 106 | "processing", 107 | "stopped" 108 | }; 109 | 110 | if (printer_state < PD_PRINTER_STATE_IDLE || 111 | printer_state - 3 > sizeof (text)) 112 | return "unknown"; 113 | 114 | return text[printer_state - PD_PRINTER_STATE_IDLE]; 115 | } 116 | 117 | gchar * 118 | pd_get_unix_user (GDBusMethodInvocation *invocation) 119 | { 120 | GError *error = NULL; 121 | gchar *ret; 122 | GDBusConnection *connection; 123 | GDBusProxy *dbus_proxy = NULL; 124 | GVariant *uid_reply = NULL; 125 | GVariantIter iter_uid; 126 | GVariant *uid = NULL; 127 | struct passwd pwd, *result; 128 | gchar *buf = NULL; 129 | long bufsize; 130 | int err; 131 | const gchar *sender; 132 | 133 | connection = g_dbus_method_invocation_get_connection (invocation); 134 | dbus_proxy = g_dbus_proxy_new_sync (connection, 135 | G_DBUS_PROXY_FLAGS_NONE, 136 | NULL, 137 | "org.freedesktop.DBus", 138 | "/org/freedesktop/DBus", 139 | "org.freedesktop.DBus", 140 | NULL, 141 | &error); 142 | if (dbus_proxy == NULL) { 143 | g_warning ("Unable to get DBus proxy: %s", error->message); 144 | g_error_free (error); 145 | goto out; 146 | } 147 | 148 | sender = g_dbus_method_invocation_get_sender (invocation); 149 | uid_reply = g_dbus_proxy_call_sync (dbus_proxy, 150 | "GetConnectionUnixUser", 151 | g_variant_new ("(s)", sender), 152 | G_DBUS_CALL_FLAGS_NONE, 153 | -1, 154 | NULL, 155 | &error); 156 | if (uid_reply == NULL) { 157 | g_warning ("GetConnectionUnixUser failed: %s", error->message); 158 | g_error_free (error); 159 | goto out; 160 | } 161 | 162 | if (g_variant_iter_init (&iter_uid, uid_reply) != 1) { 163 | g_warning ("Bad reply from GetConnectionUnixUser"); 164 | goto out; 165 | } 166 | 167 | uid = g_variant_iter_next_value (&iter_uid); 168 | if (!uid || 169 | !g_variant_is_of_type (uid, G_VARIANT_TYPE_UINT32)) { 170 | g_warning ("Bad value type from GetConnectionUnixUser"); 171 | goto out; 172 | } 173 | 174 | bufsize = sysconf (_SC_GETPW_R_SIZE_MAX); 175 | if (bufsize == -1) 176 | bufsize = 16384; 177 | 178 | buf = g_malloc (bufsize); 179 | err = getpwuid_r (g_variant_get_uint32 (uid), 180 | &pwd, 181 | buf, 182 | bufsize, 183 | &result); 184 | if (result == NULL) { 185 | if (err != 0) 186 | g_warning ("Error looking up unix user: %s", 187 | g_strerror (errno)); 188 | 189 | g_free (buf); 190 | buf = NULL; 191 | } 192 | 193 | out: 194 | if (dbus_proxy) 195 | g_object_unref (dbus_proxy); 196 | if (uid_reply) 197 | g_variant_unref (uid_reply); 198 | if (uid) 199 | g_variant_unref (uid); 200 | 201 | if (buf) { 202 | ret = g_strdup (pwd.pw_name); 203 | g_free (buf); 204 | } else 205 | ret = g_strdup (":unknown:"); 206 | 207 | return ret; 208 | } 209 | 210 | gchar ** 211 | add_or_remove_state_reason (const gchar *const *reasons, 212 | gchar add_or_remove, 213 | const gchar *reason) 214 | { 215 | gchar **strv; 216 | guint length; 217 | gint i, j; 218 | 219 | if (reasons == NULL) 220 | length = 0; 221 | else 222 | length = g_strv_length ((gchar **) reasons); 223 | 224 | strv = g_malloc0_n (2 + length, sizeof (gchar *)); 225 | for (i = 0, j = 0; reasons != NULL && reasons[i] != NULL; i++) { 226 | if (!g_strcmp0 (reasons[i], reason)) { 227 | /* Found the state reason */ 228 | if (add_or_remove == '+') 229 | /* Add: nothing to do */ 230 | break; 231 | 232 | /* Remove: skip it */ 233 | continue; 234 | } 235 | 236 | strv[j++] = g_strdup (reasons[i]); 237 | } 238 | 239 | if ((add_or_remove == '+' && reasons != NULL && reasons[i] != NULL) || 240 | (add_or_remove == '-' && i == j)) 241 | /* Nothing to do. */ 242 | goto out; 243 | 244 | if (add_or_remove == '+') 245 | strv[j++] = g_strdup (reason); 246 | 247 | out: 248 | return strv; 249 | } 250 | -------------------------------------------------------------------------------- /src/pd-device-impl.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * Copyright (C) 2014 Tim Waugh 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | * 20 | */ 21 | 22 | #include "config.h" 23 | 24 | #include 25 | #include 26 | 27 | #include "pd-common.h" 28 | #include "pd-device-impl.h" 29 | #include "pd-printer-impl.h" 30 | #include "pd-daemon.h" 31 | #include "pd-engine.h" 32 | 33 | /** 34 | * SECTION:pddevice 35 | * @title: PdDeviceImpl 36 | * @short_description: Implementation of #PdDeviceImpl 37 | * 38 | * This type provides an implementation of the #PdDeviceImpl 39 | * interface on . 40 | */ 41 | 42 | typedef struct _PdDeviceImplClass PdDeviceImplClass; 43 | 44 | /** 45 | * PdDeviceImpl: 46 | * 47 | * The #PdDeviceImpl structure contains only private data and should 48 | * only be accessed using the provided API. 49 | */ 50 | struct _PdDeviceImpl 51 | { 52 | PdDeviceSkeleton parent_instance; 53 | PdDaemon *daemon; 54 | gchar *sysfs_path; 55 | gchar *id; 56 | }; 57 | 58 | struct _PdDeviceImplClass 59 | { 60 | PdDeviceSkeletonClass parent_class; 61 | }; 62 | 63 | enum 64 | { 65 | PROP_0, 66 | PROP_DAEMON, 67 | PROP_SYSFS_PATH 68 | }; 69 | 70 | static void pd_device_iface_init (PdDeviceIface *iface); 71 | 72 | G_DEFINE_TYPE_WITH_CODE (PdDeviceImpl, pd_device_impl, PD_TYPE_DEVICE_SKELETON, 73 | G_IMPLEMENT_INTERFACE (PD_TYPE_DEVICE, pd_device_iface_init)); 74 | 75 | /* ------------------------------------------------------------------ */ 76 | 77 | static void 78 | pd_device_impl_finalize (GObject *object) 79 | { 80 | PdDeviceImpl *device = PD_DEVICE_IMPL (object); 81 | /* note: we don't hold a reference to device->daemon */ 82 | g_free (device->sysfs_path); 83 | g_free (device->id); 84 | G_OBJECT_CLASS (pd_device_impl_parent_class)->finalize (object); 85 | } 86 | 87 | static void 88 | pd_device_impl_get_property (GObject *object, 89 | guint prop_id, 90 | GValue *value, 91 | GParamSpec *pspec) 92 | { 93 | PdDeviceImpl *device = PD_DEVICE_IMPL (object); 94 | 95 | switch (prop_id) { 96 | case PROP_DAEMON: 97 | g_value_set_object (value, pd_device_impl_get_daemon (device)); 98 | break; 99 | case PROP_SYSFS_PATH: 100 | g_value_set_string (value, device->sysfs_path); 101 | break; 102 | default: 103 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 104 | break; 105 | } 106 | } 107 | 108 | static void 109 | pd_device_impl_set_property (GObject *object, 110 | guint prop_id, 111 | const GValue *value, 112 | GParamSpec *pspec) 113 | { 114 | PdDeviceImpl *device = PD_DEVICE_IMPL (object); 115 | 116 | switch (prop_id) { 117 | case PROP_DAEMON: 118 | g_assert (device->daemon == NULL); 119 | /* we don't take a reference to the daemon */ 120 | device->daemon = g_value_get_object (value); 121 | break; 122 | case PROP_SYSFS_PATH: 123 | g_assert (device->sysfs_path == NULL); 124 | /* we don't take a reference to the sysfs_path */ 125 | device->sysfs_path = g_value_dup_string (value); 126 | break; 127 | default: 128 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 129 | break; 130 | } 131 | } 132 | 133 | static void 134 | pd_device_impl_init (PdDeviceImpl *device) 135 | { 136 | g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (device), 137 | G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD); 138 | } 139 | 140 | static void 141 | pd_device_impl_class_init (PdDeviceImplClass *klass) 142 | { 143 | GObjectClass *gobject_class; 144 | 145 | gobject_class = G_OBJECT_CLASS (klass); 146 | gobject_class->finalize = pd_device_impl_finalize; 147 | gobject_class->set_property = pd_device_impl_set_property; 148 | gobject_class->get_property = pd_device_impl_get_property; 149 | 150 | /** 151 | * PdPrinterImpl:daemon: 152 | * 153 | * The #PdDaemon the printer is for. 154 | */ 155 | g_object_class_install_property (gobject_class, 156 | PROP_DAEMON, 157 | g_param_spec_object ("daemon", 158 | "Daemon", 159 | "The daemon the engine is for", 160 | PD_TYPE_DAEMON, 161 | G_PARAM_READABLE | 162 | G_PARAM_WRITABLE | 163 | G_PARAM_CONSTRUCT_ONLY | 164 | G_PARAM_STATIC_STRINGS)); 165 | 166 | /** 167 | * PdDeviceImpl:sysfs_path: 168 | * 169 | * The sysfs path for the object. 170 | */ 171 | g_object_class_install_property (gobject_class, 172 | PROP_SYSFS_PATH, 173 | g_param_spec_string ("sysfs-path", 174 | "Serial", 175 | "The sysfs path for the object", 176 | NULL, 177 | G_PARAM_READWRITE)); 178 | } 179 | 180 | /** 181 | * pd_device_impl_get_daemon: 182 | * @device: A #PdDeviceImpl. 183 | * 184 | * Gets the daemon used by @device. 185 | * 186 | * Returns: A #PdDaemon. Do not free, the object is owned by @device. 187 | */ 188 | PdDaemon * 189 | pd_device_impl_get_daemon (PdDeviceImpl *device) 190 | { 191 | g_return_val_if_fail (PD_IS_DEVICE_IMPL (device), NULL); 192 | return device->daemon; 193 | } 194 | 195 | const gchar * 196 | pd_device_impl_get_id (PdDeviceImpl *device) 197 | { 198 | GHashTable *ieee1284_id_fields = NULL; 199 | const gchar *idstring; 200 | GString *id; 201 | gchar *mfg; 202 | gchar *mdl; 203 | gchar *sn; 204 | 205 | /* shortcut */ 206 | if (device->id != NULL) 207 | goto out; 208 | 209 | /* make a unique ID for this device */ 210 | idstring = pd_device_get_ieee1284_id (PD_DEVICE (device)); 211 | ieee1284_id_fields = pd_parse_ieee1284_id (idstring); 212 | if (ieee1284_id_fields == NULL) 213 | goto out; 214 | 215 | mfg = g_hash_table_lookup (ieee1284_id_fields, "mfg"); 216 | mdl = g_hash_table_lookup (ieee1284_id_fields, "mdl"); 217 | sn = g_hash_table_lookup (ieee1284_id_fields, "sn"); 218 | id = g_string_new (""); 219 | if (mfg) 220 | g_string_append_printf (id, "%s_", mfg); 221 | if (mdl) 222 | g_string_append_printf (id, "%s_", mdl); 223 | if (sn) 224 | g_string_append_printf (id, "%s_", sn); 225 | if (id->len != 0) 226 | g_string_set_size (id, id->len - 1); 227 | else 228 | g_string_append_printf (id, "unknown-device"); 229 | 230 | device->id = g_string_free (id, FALSE); 231 | 232 | /* ensure valid */ 233 | g_strcanon (device->id, 234 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 235 | "abcdefghijklmnopqrstuvwxyz" 236 | "1234567890_", 237 | '_'); 238 | out: 239 | if (ieee1284_id_fields) 240 | g_hash_table_unref (ieee1284_id_fields); 241 | 242 | return device->id; 243 | } 244 | 245 | /* ------------------------------------------------------------------ */ 246 | 247 | static void 248 | pd_device_impl_complete_create_printer (PdDevice *_device, 249 | GDBusMethodInvocation *invocation, 250 | GVariant *options, 251 | const gchar *name, 252 | const gchar *description, 253 | const gchar *location, 254 | GVariant *defaults) 255 | { 256 | PdDeviceImpl *device = PD_DEVICE_IMPL (_device); 257 | PdPrinter *printer; 258 | GString *path; 259 | const gchar *device_uris[2]; 260 | const gchar *ieee1284_id = pd_device_get_ieee1284_id (_device); 261 | 262 | g_debug ("Creating printer from device %s", device->id); 263 | 264 | printer = pd_engine_add_printer (pd_daemon_get_engine (device->daemon), 265 | NULL, name, description, location, 266 | ieee1284_id, NULL); 267 | 268 | /* set device uri */ 269 | device_uris[0] = pd_device_get_uri (_device); 270 | device_uris[1] = NULL; 271 | pd_printer_set_device_uris (printer, device_uris); 272 | 273 | /* set job template attributes */ 274 | pd_printer_impl_do_update_defaults (PD_PRINTER_IMPL (printer), 275 | defaults); 276 | 277 | /* return object path */ 278 | path = g_string_new (""); 279 | g_string_printf (path, "/org/freedesktop/printerd/printer/%s", 280 | pd_printer_impl_get_id (PD_PRINTER_IMPL (printer))); 281 | g_dbus_method_invocation_return_value (invocation, 282 | g_variant_new ("(o)", 283 | path->str)); 284 | 285 | /* clean up */ 286 | g_string_free (path, TRUE); 287 | } 288 | 289 | /* runs in thread dedicated to handling @invocation */ 290 | static gboolean 291 | pd_device_impl_create_printer (PdDevice *_device, 292 | GDBusMethodInvocation *invocation, 293 | GVariant *options, 294 | const gchar *name, 295 | const gchar *description, 296 | const gchar *location, 297 | GVariant *defaults) 298 | { 299 | PdDeviceImpl *device = PD_DEVICE_IMPL (_device); 300 | 301 | /* Check if the user is authorized to create a printer */ 302 | if (!pd_daemon_check_authorization_sync (device->daemon, 303 | options, 304 | N_("Authentication is required to add a printer"), 305 | invocation, 306 | "org.freedesktop.printerd.all-edit", 307 | "org.freedesktop.printerd.printer-add", 308 | NULL)) 309 | goto out; 310 | 311 | pd_device_impl_complete_create_printer (_device, 312 | invocation, 313 | options, 314 | name, 315 | description, 316 | location, 317 | defaults); 318 | 319 | out: 320 | return TRUE; /* handled the method invocation */ 321 | } 322 | 323 | static void 324 | pd_device_iface_init (PdDeviceIface *iface) 325 | { 326 | iface->handle_create_printer = pd_device_impl_create_printer; 327 | } 328 | -------------------------------------------------------------------------------- /tools/pd-view.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, write to the Free Software 15 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 | 17 | from gi.repository import printerd 18 | from gi.repository import GObject 19 | from gi.repository import Gtk 20 | from gi.repository import Pango 21 | 22 | IFACE_PRINTERD_PREFIX = "org.freedesktop.printerd" 23 | 24 | IFACE_MANAGER = IFACE_PRINTERD_PREFIX + ".Manager" 25 | IFACE_DEVICE = IFACE_PRINTERD_PREFIX + ".Device" 26 | IFACE_PRINTER = IFACE_PRINTERD_PREFIX + ".Printer" 27 | IFACE_JOB = IFACE_PRINTERD_PREFIX + ".Job" 28 | 29 | class MainWindow(GObject.GObject): 30 | TVCOL_ID = 0 31 | TVCOL_NAME = 1 32 | TVCOL_STATE = 2 33 | TVCOL_REASONS = 3 34 | TVCOL_PATH = 4 35 | TVCOL_IFACE = 5 36 | 37 | def __init__ (self): 38 | super (GObject.GObject, self).__init__ () 39 | self.mainwindow = Gtk.Window () 40 | treeview = Gtk.TreeView () 41 | self.store = Gtk.TreeStore (GObject.TYPE_STRING, 42 | GObject.TYPE_STRING, 43 | GObject.TYPE_STRING, 44 | GObject.TYPE_STRING, 45 | GObject.TYPE_STRING, 46 | GObject.TYPE_OBJECT) 47 | treeview.set_model (self.store) 48 | for name, col in [("ID", self.TVCOL_ID), 49 | ("Name", self.TVCOL_NAME), 50 | ("State", self.TVCOL_STATE), 51 | ("Reasons", self.TVCOL_REASONS), 52 | ("Path", self.TVCOL_PATH)]: 53 | cell = Gtk.CellRendererText () 54 | cell.set_property ("ellipsize", Pango.EllipsizeMode.END) 55 | cell.set_property ("width-chars", 20) 56 | column = Gtk.TreeViewColumn (name, cell, text=col) 57 | column.set_resizable (True) 58 | treeview.append_column (column) 59 | 60 | self.mainwindow.add (treeview) 61 | self.mainwindow.show_all () 62 | self.mainwindow.connect ("delete-event", Gtk.main_quit) 63 | self.devices = dict() # D-Bus path to store iter 64 | self.printers = dict() # D-Bus path to store iter 65 | self.jobs = dict() # D-Bus path to store iter 66 | 67 | self.client = printerd.Client.new_sync (None) 68 | manager = self.client.get_object_manager () 69 | manager.connect ('object-added', self.object_added) 70 | manager.connect ('object-removed', self.object_removed) 71 | objects = manager.get_objects () 72 | for obj in objects: 73 | ifaces = obj.get_interfaces () 74 | for iface in ifaces: 75 | if iface.get_info ().name in [IFACE_DEVICE, IFACE_PRINTER]: 76 | self.interface_added (manager, obj, iface) 77 | 78 | for obj in objects: 79 | ifaces = obj.get_interfaces () 80 | for iface in ifaces: 81 | if iface.get_info ().name == IFACE_JOB: 82 | self.interface_added (manager, obj, iface) 83 | 84 | def object_added (self, manager, obj): 85 | print ("object added: %s" % repr (obj)) 86 | obj.connect ('interface-added', self.interface_added) 87 | obj.connect ('interface-removed', self.interface_removed) 88 | ifaces = obj.get_interfaces () 89 | for iface in ifaces: 90 | self.interface_added (manager, obj, iface) 91 | 92 | def interface_added (self, manager, obj, iface): 93 | print ("interface added: %s" % repr (iface)) 94 | name = iface.get_info ().name 95 | if name == IFACE_DEVICE: 96 | self.device_added (obj, iface) 97 | elif name == IFACE_PRINTER: 98 | self.printer_added (obj, iface) 99 | elif name == IFACE_JOB: 100 | self.job_added (obj, iface) 101 | 102 | def device_added (self, obj, iface): 103 | path = obj.get_object_path () 104 | print ("Device at %s" % path) 105 | iter = self.store.append (None) 106 | self.devices[path] = iter 107 | self.store.set (iter, self.TVCOL_NAME, "Device") 108 | self.store.set (iter, self.TVCOL_PATH, path) 109 | self.store.set (iter, self.TVCOL_IFACE, iface) 110 | 111 | def printer_added (self, obj, iface): 112 | path = obj.get_object_path () 113 | print ("Printer at %s" % path) 114 | printeriter = self.store.append (None) 115 | self.printers[path] = printeriter 116 | name = iface.get_property ('name') 117 | self.store.set (printeriter, self.TVCOL_NAME, name) 118 | self.store.set (printeriter, self.TVCOL_PATH, path) 119 | self.store.set (printeriter, self.TVCOL_IFACE, iface) 120 | iface.connect ("notify::state", self.printer_state_changed) 121 | iface.connect ("notify::state-reasons", 122 | self.printer_state_reasons_changed) 123 | 124 | self.set_printer_state (printeriter, iface) 125 | self.set_printer_state_reasons (printeriter, iface) 126 | 127 | def get_printer_path_from_iface (self, iface): 128 | obj = iface.get_object () 129 | path = obj.get_object_path () 130 | if path not in self.printers: 131 | return None 132 | 133 | return path 134 | 135 | def set_printer_state (self, printeriter, iface): 136 | statemap = { printerd.PrinterState.IDLE: "Idle", 137 | printerd.PrinterState.PROCESSING: "Processing", 138 | printerd.PrinterState.STOPPED: "Stopped" } 139 | state = iface.get_property ('state') 140 | state_str = statemap.get (state, "Unknown") 141 | self.store.set_value (printeriter, self.TVCOL_STATE, state_str) 142 | 143 | def set_printer_state_reasons (self, printeriter, iface): 144 | reasons = iface.get_property ('state-reasons') 145 | self.store.set_value (printeriter, self.TVCOL_REASONS, str (reasons)) 146 | 147 | def printer_state_changed (self, iface, param): 148 | path = self.get_printer_path_from_iface (iface) 149 | if path == None: 150 | print ("Non-existent printer changed?!") 151 | return 152 | 153 | print (path + " changed state") 154 | self.set_printer_state (self.printers[path], iface) 155 | 156 | def printer_state_reasons_changed (self, iface, param): 157 | path = self.get_printer_path_from_iface (iface) 158 | if path == None: 159 | print ("Non-existent printer changed?!") 160 | return 161 | 162 | print (path + " changed state-reasons") 163 | self.set_printer_state_reasons (self.printers[path], iface) 164 | 165 | def job_added (self, obj, iface): 166 | path = obj.get_object_path () 167 | print ("Job at %s" % path) 168 | printer = iface.get_property ('printer') 169 | if not printer in self.printers: 170 | print ("Orphan job?!") 171 | return 172 | 173 | jobiter = self.store.append (self.printers[printer]) 174 | self.jobs[path] = jobiter 175 | self.store.set (jobiter, self.TVCOL_ID, str (iface.get_property ('id'))) 176 | self.store.set (jobiter, self.TVCOL_NAME, iface.get_property ('name')) 177 | self.store.set (jobiter, self.TVCOL_PATH, path) 178 | self.store.set (jobiter, self.TVCOL_IFACE, iface) 179 | iface.connect ("notify::state", self.job_state_changed) 180 | iface.connect ("notify::state-reasons", self.job_state_reasons_changed) 181 | 182 | self.set_job_state (jobiter, iface) 183 | self.set_job_state_reasons (jobiter, iface) 184 | 185 | def get_job_path_from_iface (self, iface): 186 | obj = iface.get_object () 187 | path = obj.get_object_path () 188 | if path not in self.jobs: 189 | return None 190 | 191 | return path 192 | 193 | def set_job_state (self, jobiter, iface): 194 | statemap = { printerd.JobState.PENDING: "Pending", 195 | printerd.JobState.PENDING_HELD: "Held", 196 | printerd.JobState.PROCESSING: "Processing", 197 | printerd.JobState.PROCESSING_STOPPED: "Paused", 198 | printerd.JobState.CANCELED: "Canceled", 199 | printerd.JobState.ABORTED: "Aborted", 200 | printerd.JobState.COMPLETED: "Completed" } 201 | state = iface.get_property ('state') 202 | state_str = statemap.get (state, "Unknown") 203 | self.store.set_value (jobiter, self.TVCOL_STATE, state_str) 204 | 205 | def job_state_changed (self, iface, param): 206 | path = self.get_job_path_from_iface (iface) 207 | if path == None: 208 | print ("Non-existent job changed?!") 209 | return 210 | 211 | print (path + " changed state") 212 | self.set_job_state (self.jobs[path], iface) 213 | 214 | def set_job_state_reasons (self, jobiter, iface): 215 | reasons = iface.get_property ('state-reasons') 216 | self.store.set_value (jobiter, self.TVCOL_REASONS, str (reasons)) 217 | 218 | def job_state_reasons_changed (self, iface, param): 219 | path = self.get_job_path_from_iface (iface) 220 | if path == None: 221 | print ("Non-existent job changed?!") 222 | return 223 | 224 | print (path + " changed state-reasons") 225 | self.set_job_state_reasons (self.jobs[path], iface) 226 | 227 | def object_removed (self, manager, obj): 228 | path = obj.get_property ('g-object-path') 229 | print ("object removed: %s" % path) 230 | if path in self.jobs: 231 | iter = self.jobs[path] 232 | elif path in self.printers: 233 | iter = self.printers[path] 234 | while self.store.iter_has_child (iter): 235 | print ("Iter for path %s has child; removing" % path) 236 | jobiter = self.store.iter_nth_child (iter, 0) 237 | jobpath = self.store.get_value (jobiter, self.TVCOL_PATH) 238 | del self.jobs[jobpath] 239 | self.store.remove (jobiter) 240 | elif path in self.devices: 241 | iter = self.devices[path] 242 | else: 243 | print ("unknown path: %s" % path) 244 | return 245 | 246 | if iter == None: 247 | return 248 | 249 | self.store.remove (iter) 250 | 251 | def interface_removed (self, manager, obj, iface): 252 | print ("interface removed: %s" % repr (iface)) 253 | name = iface.get_info ().name 254 | path = obj.get_object_path () 255 | if name == IFACE_JOB: 256 | if not path in self.jobs: 257 | print ("Non-existent job removed?!") 258 | return 259 | 260 | self.store.remove (self.jobs[path]) 261 | del self.jobs[path] 262 | elif name == IFACE_PRINTER: 263 | if not path in self.printers: 264 | print ("Non-existent job removed?!") 265 | return 266 | 267 | self.store.remove (self.printers[path]) 268 | del self.printers[path] 269 | 270 | mainwindow = MainWindow () 271 | Gtk.main () 272 | -------------------------------------------------------------------------------- /src/pd-manager-impl.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * Copyright (C) 2014 Tim Waugh 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | * 20 | */ 21 | 22 | #include "config.h" 23 | 24 | #include 25 | #include 26 | 27 | #include "pd-manager-impl.h" 28 | #include "pd-daemon.h" 29 | #include "pd-engine.h" 30 | #include "pd-device-impl.h" 31 | #include "pd-printer-impl.h" 32 | #include "pd-log.h" 33 | 34 | /** 35 | * SECTION:pdmanager 36 | * @title: PdManagerImpl 37 | * @short_description: Implementation of #PdManagerImpl 38 | * 39 | * This type provides an implementation of the #PdManagerImpl 40 | * interface on . 41 | */ 42 | 43 | typedef struct _PdManagerImplClass PdManagerImplClass; 44 | 45 | /** 46 | * PdManagerImpl: 47 | * 48 | * The #PdManagerImpl structure contains only private data and should 49 | * only be accessed using the provided API. 50 | */ 51 | struct _PdManagerImpl 52 | { 53 | PdManagerSkeleton parent_instance; 54 | PdDaemon *daemon; 55 | }; 56 | 57 | struct _PdManagerImplClass 58 | { 59 | PdManagerSkeletonClass parent_class; 60 | }; 61 | 62 | enum 63 | { 64 | PROP_0, 65 | PROP_DAEMON 66 | }; 67 | 68 | static void pd_manager_iface_init (PdManagerIface *iface); 69 | 70 | G_DEFINE_TYPE_WITH_CODE (PdManagerImpl, pd_manager_impl, PD_TYPE_MANAGER_SKELETON, 71 | G_IMPLEMENT_INTERFACE (PD_TYPE_MANAGER, pd_manager_iface_init)); 72 | 73 | /* ------------------------------------------------------------------ */ 74 | 75 | static void 76 | pd_manager_impl_finalize (GObject *object) 77 | { 78 | /* PdManagerImpl *manager = PD_MANAGER_IMPL (object); */ 79 | G_OBJECT_CLASS (pd_manager_impl_parent_class)->finalize (object); 80 | } 81 | 82 | static void 83 | pd_manager_impl_get_property (GObject *object, 84 | guint prop_id, 85 | GValue *value, 86 | GParamSpec *pspec) 87 | { 88 | PdManagerImpl *manager = PD_MANAGER_IMPL (object); 89 | 90 | switch (prop_id) { 91 | case PROP_DAEMON: 92 | g_value_set_object (value, pd_manager_impl_get_daemon (manager)); 93 | break; 94 | default: 95 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 96 | break; 97 | } 98 | } 99 | 100 | static void 101 | pd_manager_impl_set_property (GObject *object, 102 | guint prop_id, 103 | const GValue *value, 104 | GParamSpec *pspec) 105 | { 106 | PdManagerImpl *manager = PD_MANAGER_IMPL (object); 107 | 108 | switch (prop_id) { 109 | case PROP_DAEMON: 110 | g_assert (manager->daemon == NULL); 111 | /* we don't take a reference to the daemon */ 112 | manager->daemon = g_value_get_object (value); 113 | break; 114 | default: 115 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 116 | break; 117 | } 118 | } 119 | 120 | static void 121 | pd_manager_impl_init (PdManagerImpl *manager) 122 | { 123 | g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (manager), 124 | G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD); 125 | } 126 | 127 | static void 128 | pd_manager_impl_class_init (PdManagerImplClass *klass) 129 | { 130 | GObjectClass *gobject_class; 131 | 132 | gobject_class = G_OBJECT_CLASS (klass); 133 | gobject_class->finalize = pd_manager_impl_finalize; 134 | gobject_class->set_property = pd_manager_impl_set_property; 135 | gobject_class->get_property = pd_manager_impl_get_property; 136 | 137 | /** 138 | * PdManagerImpl:daemon: 139 | * 140 | * The #PdDaemon for the object. 141 | */ 142 | g_object_class_install_property (gobject_class, 143 | PROP_DAEMON, 144 | g_param_spec_object ("daemon", 145 | "Daemon", 146 | "The daemon for the object", 147 | PD_TYPE_DAEMON, 148 | G_PARAM_READABLE | 149 | G_PARAM_WRITABLE | 150 | G_PARAM_CONSTRUCT_ONLY | 151 | G_PARAM_STATIC_STRINGS)); 152 | } 153 | 154 | /** 155 | * pd_manager_impl_new: 156 | * @daemon: A #PdDaemon. 157 | * 158 | * Creates a new #PdManagerImpl instance. 159 | * 160 | * Returns: A new #PdManagerImpl. Free with g_object_unref(). 161 | */ 162 | PdManager * 163 | pd_manager_impl_new (PdDaemon *daemon) 164 | { 165 | g_return_val_if_fail (PD_IS_DAEMON (daemon), NULL); 166 | return PD_MANAGER (g_object_new (PD_TYPE_MANAGER_IMPL, 167 | "daemon", daemon, 168 | "version", PACKAGE_VERSION, 169 | NULL)); 170 | } 171 | 172 | /** 173 | * pd_manager_impl_get_daemon: 174 | * @manager: A #PdManagerImpl. 175 | * 176 | * Gets the daemon used by @manager. 177 | * 178 | * Returns: A #PdDaemon. Do not free, the object is owned by @manager. 179 | */ 180 | PdDaemon * 181 | pd_manager_impl_get_daemon (PdManagerImpl *manager) 182 | { 183 | g_return_val_if_fail (PD_IS_MANAGER_IMPL (manager), NULL); 184 | return manager->daemon; 185 | } 186 | 187 | /* ------------------------------------------------------------------ */ 188 | 189 | /* runs in thread dedicated to handling @invocation */ 190 | static gboolean 191 | pd_manager_impl_get_printers (PdManager *_manager, 192 | GDBusMethodInvocation *invocation) 193 | { 194 | PdManagerImpl *manager = PD_MANAGER_IMPL (_manager); 195 | PdDaemon *daemon = pd_manager_impl_get_daemon (manager); 196 | PdEngine *engine = pd_daemon_get_engine (daemon); 197 | GList *printer_ids = pd_engine_dup_printer_ids (engine); 198 | GList *each; 199 | GVariantBuilder builder; 200 | GString *path = g_string_new (""); 201 | 202 | manager_debug (_manager, "Handling GetPrinters"); 203 | g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ao)")); 204 | g_variant_builder_open (&builder, G_VARIANT_TYPE ("ao")); 205 | for (each = printer_ids; each; each = g_list_next (each)) { 206 | g_string_printf (path, "/org/freedesktop/printerd/printer/%s", 207 | (const gchar *) each->data); 208 | g_variant_builder_add (&builder, "o", path->str); 209 | } 210 | g_variant_builder_close (&builder); 211 | g_dbus_method_invocation_return_value (invocation, 212 | g_variant_builder_end (&builder)); 213 | g_string_free (path, TRUE); 214 | g_list_foreach (printer_ids, (GFunc) g_free, NULL); 215 | g_list_free (printer_ids); 216 | return TRUE; /* handled the method invocation */ 217 | } 218 | 219 | /* runs in thread dedicated to handling @invocation */ 220 | static gboolean 221 | pd_manager_impl_get_devices (PdManager *_manager, 222 | GDBusMethodInvocation *invocation) 223 | { 224 | PdManagerImpl *manager = PD_MANAGER_IMPL (_manager); 225 | PdDaemon *daemon = pd_manager_impl_get_daemon (manager); 226 | PdEngine *engine = pd_daemon_get_engine (daemon); 227 | GList *devices = pd_engine_get_devices (engine); 228 | GList *each; 229 | GVariantBuilder builder; 230 | GString *path = g_string_new (""); 231 | 232 | manager_debug (_manager, "Handling GetDevices"); 233 | g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ao)")); 234 | g_variant_builder_open (&builder, G_VARIANT_TYPE ("ao")); 235 | for (each = devices; each; each = g_list_next (each)) { 236 | const gchar *id; 237 | id = pd_device_impl_get_id (PD_DEVICE_IMPL (each->data)); 238 | g_string_printf (path, "/org/freedesktop/printerd/device/%s", id); 239 | g_variant_builder_add (&builder, "o", path->str); 240 | } 241 | g_variant_builder_close (&builder); 242 | g_dbus_method_invocation_return_value (invocation, 243 | g_variant_builder_end (&builder)); 244 | 245 | g_list_foreach (devices, (GFunc) g_object_unref, NULL); 246 | g_list_free (devices); 247 | g_string_free (path, TRUE); 248 | return TRUE; /* handled the method invocation */ 249 | } 250 | 251 | static void 252 | pd_manager_impl_complete_create_printer (PdManager *_manager, 253 | GDBusMethodInvocation *invocation, 254 | GVariant *options, 255 | const gchar *name, 256 | const gchar *description, 257 | const gchar *location, 258 | const gchar *const *device_uris, 259 | GVariant *defaults) 260 | { 261 | PdManagerImpl *manager = PD_MANAGER_IMPL (_manager); 262 | PdPrinter *printer; 263 | gchar *path; 264 | GError *error = NULL; 265 | 266 | manager_debug (_manager, "Creating printer"); 267 | 268 | printer = pd_engine_add_printer (pd_daemon_get_engine (manager->daemon), 269 | options, name, description, location, 270 | NULL, &error); 271 | 272 | if (printer == NULL) { 273 | manager_debug (_manager, "Error: %s", error->message); 274 | g_dbus_method_invocation_return_gerror (invocation, error); 275 | return; 276 | } 277 | 278 | /* set device URIs */ 279 | pd_printer_set_device_uris (printer, device_uris); 280 | 281 | /* set job template attribute */ 282 | pd_printer_impl_do_update_defaults (PD_PRINTER_IMPL (printer), 283 | defaults); 284 | 285 | /* return object path */ 286 | path = g_strdup_printf ("/org/freedesktop/printerd/printer/%s", 287 | pd_printer_impl_get_id (PD_PRINTER_IMPL (printer))); 288 | g_dbus_method_invocation_return_value (invocation, 289 | g_variant_new ("(o)", 290 | path)); 291 | 292 | /* clean up */ 293 | g_free (path); 294 | } 295 | 296 | /* runs in thread dedicated to handling @invocation */ 297 | static gboolean 298 | pd_manager_impl_create_printer (PdManager *_manager, 299 | GDBusMethodInvocation *invocation, 300 | GVariant *options, 301 | const gchar *name, 302 | const gchar *description, 303 | const gchar *location, 304 | const gchar *const *device_uris, 305 | GVariant *defaults) 306 | { 307 | PdManagerImpl *manager = PD_MANAGER_IMPL (_manager); 308 | 309 | /* Check if the user is authorized to create a printer */ 310 | if (!pd_daemon_check_authorization_sync (manager->daemon, 311 | options, 312 | N_("Authentication is required to add a printer"), 313 | invocation, 314 | "org.freedesktop.printerd.all-edit", 315 | "org.freedesktop.printerd.printer-add", 316 | NULL)) 317 | goto out; 318 | 319 | pd_manager_impl_complete_create_printer (_manager, 320 | invocation, 321 | options, 322 | name, 323 | description, 324 | location, 325 | device_uris, 326 | defaults); 327 | 328 | out: 329 | return TRUE; /* handled the method invocation */ 330 | } 331 | 332 | /* runs in thread dedicated to handling @invocation */ 333 | static gboolean 334 | pd_manager_impl_delete_printer (PdManager *_manager, 335 | GDBusMethodInvocation *invocation, 336 | GVariant *options, 337 | const gchar *printer_path) 338 | { 339 | PdManagerImpl *manager = PD_MANAGER_IMPL (_manager); 340 | PdEngine *engine = pd_daemon_get_engine (manager->daemon); 341 | 342 | manager_debug (_manager, "Deleting printer %s", printer_path); 343 | 344 | if (pd_engine_remove_printer (engine, printer_path)) 345 | g_dbus_method_invocation_return_value (invocation, 346 | g_variant_new ("()")); 347 | else { 348 | manager_debug (_manager, "Printer %s not found", printer_path); 349 | g_dbus_method_invocation_return_error (invocation, 350 | PD_ERROR, 351 | PD_ERROR_FAILED, 352 | N_("Not found")); 353 | } 354 | 355 | return TRUE; 356 | } 357 | 358 | static void 359 | pd_manager_iface_init (PdManagerIface *iface) 360 | { 361 | iface->handle_get_printers = pd_manager_impl_get_printers; 362 | iface->handle_get_devices = pd_manager_impl_get_devices; 363 | iface->handle_create_printer = pd_manager_impl_create_printer; 364 | iface->handle_delete_printer = pd_manager_impl_delete_printer; 365 | } 366 | -------------------------------------------------------------------------------- /src/pd-daemon.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- 2 | * 3 | * Copyright (C) 2012 Richard Hughes 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | #include "config.h" 22 | #include 23 | 24 | #include "pd-daemon.h" 25 | #include "pd-engine.h" 26 | 27 | /** 28 | * SECTION:printerddaemon 29 | * @title: PdDaemon 30 | * @short_description: Main daemon object 31 | * 32 | * Object holding all global state. 33 | */ 34 | 35 | typedef struct _PdDaemonClass PdDaemonClass; 36 | 37 | /** 38 | * PdDaemon: 39 | * 40 | * The #PdDaemon structure contains only private data and should 41 | * only be accessed using the provided API. 42 | */ 43 | struct _PdDaemon 44 | { 45 | GObject parent_instance; 46 | GDBusConnection *connection; 47 | gboolean is_session; 48 | GDBusObjectManagerServer *object_manager; 49 | PdEngine *engine; 50 | PolkitAuthority *authority; 51 | }; 52 | 53 | struct _PdDaemonClass 54 | { 55 | GObjectClass parent_class; 56 | }; 57 | 58 | enum 59 | { 60 | PROP_0, 61 | PROP_CONNECTION, 62 | PROP_IS_SESSION, 63 | PROP_OBJECT_MANAGER, 64 | }; 65 | 66 | G_DEFINE_TYPE (PdDaemon, pd_daemon, G_TYPE_OBJECT); 67 | 68 | static void 69 | pd_daemon_dispose (GObject *object) 70 | { 71 | PdDaemon *daemon = PD_DAEMON (object); 72 | 73 | g_debug ("[Daemon] Dispose"); 74 | g_object_run_dispose ((GObject *)daemon->engine); 75 | 76 | if (G_OBJECT_CLASS (pd_daemon_parent_class)->dispose != NULL) 77 | G_OBJECT_CLASS (pd_daemon_parent_class)->dispose (object); 78 | } 79 | 80 | static void 81 | pd_daemon_finalize (GObject *object) 82 | { 83 | PdDaemon *daemon = PD_DAEMON (object); 84 | 85 | g_debug ("[Daemon] Finalize"); 86 | if (daemon->authority) 87 | g_object_unref (daemon->authority); 88 | 89 | g_object_unref (daemon->object_manager); 90 | g_object_unref (daemon->connection); 91 | g_object_unref (daemon->engine); 92 | 93 | if (G_OBJECT_CLASS (pd_daemon_parent_class)->finalize != NULL) 94 | G_OBJECT_CLASS (pd_daemon_parent_class)->finalize (object); 95 | } 96 | 97 | static void 98 | pd_daemon_get_property (GObject *object, 99 | guint prop_id, 100 | GValue *value, 101 | GParamSpec *pspec) 102 | { 103 | PdDaemon *daemon = PD_DAEMON (object); 104 | switch (prop_id) { 105 | case PROP_CONNECTION: 106 | g_value_set_object (value, pd_daemon_get_connection (daemon)); 107 | break; 108 | case PROP_IS_SESSION: 109 | g_value_set_boolean (value, daemon->is_session); 110 | break; 111 | case PROP_OBJECT_MANAGER: 112 | g_value_set_object (value, pd_daemon_get_object_manager (daemon)); 113 | break; 114 | default: 115 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 116 | break; 117 | } 118 | } 119 | 120 | static void 121 | pd_daemon_set_property (GObject *object, 122 | guint prop_id, 123 | const GValue *value, 124 | GParamSpec *pspec) 125 | { 126 | PdDaemon *daemon = PD_DAEMON (object); 127 | switch (prop_id) { 128 | case PROP_CONNECTION: 129 | g_assert (daemon->connection == NULL); 130 | daemon->connection = g_value_dup_object (value); 131 | break; 132 | case PROP_IS_SESSION: 133 | daemon->is_session = g_value_get_boolean (value); 134 | break; 135 | default: 136 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 137 | break; 138 | } 139 | } 140 | 141 | static void 142 | pd_daemon_init (PdDaemon *daemon) 143 | { 144 | } 145 | 146 | static void 147 | pd_daemon_constructed (GObject *object) 148 | { 149 | PdDaemon *daemon = PD_DAEMON (object); 150 | GError *error = NULL; 151 | 152 | if (daemon->is_session) 153 | daemon->authority = NULL; 154 | else { 155 | daemon->authority = polkit_authority_get_sync (NULL, &error); 156 | if (daemon->authority == NULL) { 157 | g_error ("Error initializing PolicyKit authority: %s (%s, %d)", 158 | error->message, g_quark_to_string (error->domain), error->code); 159 | g_error_free (error); 160 | } 161 | } 162 | daemon->object_manager = g_dbus_object_manager_server_new ("/org/freedesktop/printerd"); 163 | daemon->engine = pd_engine_new (daemon); 164 | pd_engine_start (daemon->engine); 165 | 166 | /* Export the ObjectManager */ 167 | g_dbus_object_manager_server_set_connection (daemon->object_manager, 168 | daemon->connection); 169 | 170 | if (G_OBJECT_CLASS (pd_daemon_parent_class)->constructed != NULL) 171 | G_OBJECT_CLASS (pd_daemon_parent_class)->constructed (object); 172 | } 173 | 174 | 175 | static void 176 | pd_daemon_class_init (PdDaemonClass *klass) 177 | { 178 | GObjectClass *gobject_class; 179 | 180 | gobject_class = G_OBJECT_CLASS (klass); 181 | gobject_class->dispose = pd_daemon_dispose; 182 | gobject_class->finalize = pd_daemon_finalize; 183 | gobject_class->constructed = pd_daemon_constructed; 184 | gobject_class->set_property = pd_daemon_set_property; 185 | gobject_class->get_property = pd_daemon_get_property; 186 | 187 | /** 188 | * PdDaemon:connection: 189 | * 190 | * The #GDBusConnection the daemon is for. 191 | */ 192 | g_object_class_install_property (gobject_class, 193 | PROP_CONNECTION, 194 | g_param_spec_object ("connection", 195 | "Connection", 196 | "The D-Bus connection the daemon is for", 197 | G_TYPE_DBUS_CONNECTION, 198 | G_PARAM_READABLE | 199 | G_PARAM_WRITABLE | 200 | G_PARAM_CONSTRUCT_ONLY | 201 | G_PARAM_STATIC_STRINGS)); 202 | 203 | /** 204 | * PdDaemon:is-session: 205 | * 206 | * Whether we are running on the session bus (for testing). 207 | */ 208 | g_object_class_install_property (gobject_class, 209 | PROP_IS_SESSION, 210 | g_param_spec_boolean ("is-session", 211 | "is-session", 212 | "Whether the daemon is on the session bus", 213 | FALSE, 214 | G_PARAM_READABLE | 215 | G_PARAM_WRITABLE | 216 | G_PARAM_CONSTRUCT_ONLY)); 217 | 218 | /** 219 | * PdDaemon:object-manager: 220 | * 221 | * The #GDBusObjectManager used by the daemon 222 | */ 223 | g_object_class_install_property (gobject_class, 224 | PROP_OBJECT_MANAGER, 225 | g_param_spec_object ("object-manager", 226 | "Object Manager", 227 | "The D-Bus Object Manager server used by the daemon", 228 | G_TYPE_DBUS_OBJECT_MANAGER_SERVER, 229 | G_PARAM_READABLE | 230 | G_PARAM_STATIC_STRINGS)); 231 | } 232 | 233 | /** 234 | * pd_daemon_new: 235 | * @connection: A #GDBusConnection. 236 | * 237 | * Create a new daemon object for exporting objects on @connection. 238 | * 239 | * Returns: A #PdDaemon object. Free with g_object_unref(). 240 | */ 241 | PdDaemon * 242 | pd_daemon_new (GDBusConnection *connection, 243 | gboolean is_session) 244 | { 245 | g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); 246 | return PD_DAEMON (g_object_new (PD_TYPE_DAEMON, 247 | "connection", connection, 248 | "is-session", is_session, 249 | NULL)); 250 | } 251 | 252 | /** 253 | * pd_daemon_get_connection: 254 | * @daemon: A #PdDaemon. 255 | * 256 | * Gets the D-Bus connection used by @daemon. 257 | * 258 | * Returns: A #GDBusConnection. Do not free, the object is owned by @daemon. 259 | */ 260 | GDBusConnection * 261 | pd_daemon_get_connection (PdDaemon *daemon) 262 | { 263 | g_return_val_if_fail (PD_IS_DAEMON (daemon), NULL); 264 | return daemon->connection; 265 | } 266 | 267 | /** 268 | * pd_daemon_get_object_manager: 269 | * @daemon: A #PdDaemon. 270 | * 271 | * Gets the D-Bus object manager used by @daemon. 272 | * 273 | * Returns: A #GDBusObjectManagerServer. Do not free, the object is owned by @daemon. 274 | */ 275 | GDBusObjectManagerServer * 276 | pd_daemon_get_object_manager (PdDaemon *daemon) 277 | { 278 | g_return_val_if_fail (PD_IS_DAEMON (daemon), NULL); 279 | return daemon->object_manager; 280 | } 281 | 282 | /** 283 | * pd_daemon_get_authority: 284 | * @daemon: A #PdDaemon. 285 | * 286 | * Gets the PolicyKit authority used by @daemon. 287 | * 288 | * Returns: A #PolkitAuthority instance. Do not free, the object is owned by @daemon. 289 | */ 290 | PolkitAuthority * 291 | pd_daemon_get_authority (PdDaemon *daemon) 292 | { 293 | g_return_val_if_fail (PD_IS_DAEMON (daemon), NULL); 294 | return daemon->authority; 295 | } 296 | 297 | /** 298 | * pd_daemon_find_object: 299 | * @daemon: A #PdDaemon. 300 | * @object_path: An object path 301 | * 302 | * Finds an exported object with the object path given by @object_path. 303 | * 304 | * Returns: (transfer full): A #PdObject or %NULL if not found. Free with g_object_unref(). 305 | */ 306 | PdObject * 307 | pd_daemon_find_object (PdDaemon *daemon, 308 | const gchar *object_path) 309 | { 310 | return (PdObject *) g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (daemon->object_manager), 311 | object_path); 312 | } 313 | 314 | /** 315 | * pd_daemon_get_engine: 316 | * @daemon: A #PdDaemon. 317 | * 318 | * Gets the engine used by @daemon. 319 | * 320 | * Returns: A #PdEngine instance. Do not free, the object is owned by @daemon. 321 | */ 322 | PdEngine * 323 | pd_daemon_get_engine (PdDaemon *daemon) 324 | { 325 | g_return_val_if_fail (PD_IS_DAEMON (daemon), NULL); 326 | return daemon->engine; 327 | } 328 | 329 | /** 330 | * pd_daemon_check_authorization_sync: 331 | * @daemon: A #PdDaemon. 332 | * @action_id: The action ID to check against. 333 | * @options: Variant representing options. 334 | * @description: Description text for the action. 335 | * @invociation: A #GDBusMethodInvocation. 336 | * 337 | * Checks authorization using polkit. 338 | * 339 | * Returns: True if the subject is authorized. 340 | */ 341 | gboolean 342 | pd_daemon_check_authorization_sync (PdDaemon *daemon, 343 | GVariant *options, 344 | const gchar *message, 345 | GDBusMethodInvocation *invocation, 346 | const gchar *first_action_id, 347 | ...) 348 | { 349 | va_list va_args; 350 | const gchar *action_id, *next_action_id; 351 | gboolean ret = FALSE; 352 | GError *error = NULL; 353 | const gchar *sender; 354 | PolkitSubject *subject; 355 | PolkitCheckAuthorizationFlags flags = 0; 356 | PolkitAuthorizationResult *result = NULL; 357 | 358 | if (daemon->is_session) { 359 | ret = TRUE; 360 | goto out; 361 | } 362 | 363 | sender = g_dbus_method_invocation_get_sender (invocation); 364 | subject = polkit_system_bus_name_new (sender); 365 | 366 | va_start (va_args, first_action_id); 367 | action_id = first_action_id; 368 | while (action_id) { 369 | next_action_id = va_arg (va_args, const gchar *); 370 | if (!next_action_id) 371 | flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION; 372 | g_clear_error (&error); 373 | result = polkit_authority_check_authorization_sync (daemon->authority, 374 | subject, 375 | action_id, 376 | NULL, 377 | flags, 378 | NULL, 379 | &error); 380 | if (result) 381 | break; 382 | 383 | action_id = next_action_id; 384 | } 385 | 386 | g_object_unref (subject); 387 | if (error) { 388 | g_warning ("[Daemon] Checking authorization: %s", 389 | error->message); 390 | g_dbus_method_invocation_return_gerror (invocation, 391 | error); 392 | g_error_free (error); 393 | goto out; 394 | } 395 | 396 | if (result == NULL || 397 | !polkit_authorization_result_get_is_authorized (result)) { 398 | g_debug ("[Daemon] %s not authorized", sender); 399 | g_dbus_method_invocation_return_error (invocation, 400 | PD_ERROR, 401 | PD_ERROR_FAILED, 402 | "%s", message); 403 | goto out; 404 | } 405 | 406 | /* Authorized */ 407 | g_debug ("[Daemon] %s authorized for %s", sender, action_id); 408 | ret = TRUE; 409 | 410 | out: 411 | if (result) 412 | g_object_unref (result); 413 | 414 | return ret; 415 | } 416 | --------------------------------------------------------------------------------