diff --git a/Makefile.am b/Makefile.am index 9352633..06a60b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -185,12 +185,14 @@ udevrulesdir=$(sysconfdir)/udev/rules.d udevrules_DATA=udev/70-printers.rules udev_udev_configure_printer_SOURCES=\ udev/udev-configure-printer.c -udev_udev_configure_printer_LDADD=-lcups -ludev -lusb $(GLIB_LIBS) +udev_udev_configure_printer_LDADD=-lcups -ludev -lusb $(GLIB_LIBS) -ldbus-glib-1 -ldbus-1 + udevhelperdir=$(sysconfdir)/udev udevhelper_PROGRAMS=\ udev/udev-configure-printer udevhelper_SCRIPTS=\ udev/udev-add-printer +INCLUDES = -I`pkg-config --cflags dbus-1 dbus-glib-1 ` endif man_MANS= \ diff --git a/udev/udev-configure-printer.c b/udev/udev-configure-printer.c index ebe891b..7710ac4 100644 --- a/udev/udev-configure-printer.c +++ b/udev/udev-configure-printer.c @@ -47,11 +47,19 @@ #include <unistd.h> #include <usb.h> #include <glib.h> +#include <dbus/dbus.h> #define DISABLED_REASON "Unplugged or turned off" #define MATCH_ONLY_DISABLED 1 #define USB_URI_MAP "/var/run/udev-configure-printer/usb-uris" +#define DBUS_PATH_ORG_FREEDESKTOP_DBUS "/com/redhat/NewPrinterNotification" +#define DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "com.redhat.NewPrinterNotification" +#define DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "com.redhat.NewPrinterNotification" + +static char * global_make = ""; +static char * global_model = ""; + struct device_uris { size_t n_uris; @@ -96,6 +104,7 @@ static const char *device_uri_types[] = static int device_uri_type (const char *uri) { + //syslog (LOG_DEBUG, "device_uri_type()"); int slen = strcspn (uri, ":"); int i; int n = sizeof (device_uri_types) / sizeof (device_uri_types[0]); @@ -111,6 +120,7 @@ static void add_device_uri (struct device_uris *uris, const char *uri) { + //syslog (LOG_DEBUG, "add_device_uri ()"); char *uri_copy = strdup (uri); if (!uri_copy) { @@ -154,6 +164,7 @@ add_device_uri (struct device_uris *uris, static void free_device_uris (struct device_uris *uris) { + //syslog (LOG_DEBUG, "free_device_uris()"); size_t i; for (i = 0; i < uris->n_uris; i++) free (uris->uri[i]); @@ -165,6 +176,7 @@ add_usb_uri_mapping (struct usb_uri_map **map, const char *devpath, const struct device_uris *uris) { + //syslog (LOG_DEBUG, "add_usb_uri_mapping()"); struct usb_uri_map_entry *entry, **prev; size_t i; prev = &(*map)->entries; @@ -190,6 +202,7 @@ add_usb_uri_mapping (struct usb_uri_map **map, static struct usb_uri_map * read_usb_uri_map (void) { +// syslog (LOG_DEBUG, "read_usb_uri_map()"); int fd = open (USB_URI_MAP, O_RDWR); struct usb_uri_map *map = NULL; struct flock lock; @@ -297,6 +310,7 @@ read_usb_uri_map (void) static void write_usb_uri_map (struct usb_uri_map *map) { + syslog (LOG_DEBUG, "write_usb_uri_map()"); struct usb_uri_map_entry *entry; int fd = map->fd; FILE *f; @@ -348,6 +362,7 @@ write_usb_uri_map (struct usb_uri_map *map) static void free_usb_uri_map (struct usb_uri_map *map) { +// syslog (LOG_DEBUG, "free_usb_uri_map()"); struct usb_uri_map_entry *entry, *next; for (entry = map->entries; entry; entry = next) { @@ -366,6 +381,7 @@ free_usb_uri_map (struct usb_uri_map *map) static void free_device_id (struct device_id *id) { +// syslog (LOG_DEBUG, "free_device_id()"); free (id->full_device_id); free (id->mfg); free (id->mdl); @@ -376,6 +392,7 @@ static void parse_device_id (const char *device_id, struct device_id *id) { +// syslog (LOG_DEBUG, "parse_device_id()"); char *fieldname; char *start, *end; size_t len; @@ -448,6 +465,7 @@ device_id_from_devpath (const char *devpath, char *usbserial, size_t usbseriallen, char *usblpdev, size_t usblpdevlen) { +// syslog (LOG_DEBUG, "device_id_from_devpath()"); struct usb_uri_map_entry *entry; struct udev *udev; struct udev_device *dev, *parent_dev = NULL; @@ -754,6 +772,7 @@ uri_from_bdaddr (const char *devpath) static const char * no_password (const char *prompt) { +// syslog (LOG_DEBUG, "no_password()"); return ""; } @@ -762,6 +781,7 @@ cupsDoRequestOrDie (http_t *http, ipp_t *request, const char *resource) { +// syslog (LOG_DEBUG, "cupsDoRequestOrDie()"); ipp_t *answer = cupsDoRequest (http, request, resource); if (answer == NULL) { @@ -781,6 +801,356 @@ cupsDoRequestOrDie (http_t *http, return answer; } +static void +PrinterEnabled () +{ + syslog (LOG_DEBUG, "PrinterEnabled()"); + DBusMessage *message = NULL; + DBusConnection *connection = NULL; + DBusError error; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "PrinterEnabled"); + if (message == NULL) + goto finish_error1; + + dbus_message_append_args (message, + DBUS_TYPE_STRING, &global_make, + DBUS_TYPE_STRING, &global_model, DBUS_TYPE_INVALID); + + if (!dbus_connection_send (connection, message, NULL)) + { + dbus_message_unref (message); + message = NULL; + } + +finish_error1: + if(message) + dbus_message_unref (message); +} +static void +PrinterDisabled () +{ + syslog (LOG_DEBUG, "PrinterDisabled()"); + DBusMessage *message = NULL; + DBusConnection *connection = NULL; + DBusError error; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "PrinterDisabled"); + if (message == NULL) + goto finish_error2; + + dbus_message_append_args (message, + DBUS_TYPE_STRING, &global_make, + DBUS_TYPE_STRING, &global_model, DBUS_TYPE_INVALID); + + if (!dbus_connection_send (connection, message, NULL)) + { + dbus_message_unref (message); + message = NULL; + } + +finish_error2: + if(message) + dbus_message_unref (message); +} +static void +InstallSpoolerFailed () +{ + syslog (LOG_DEBUG, "InstallSpoolerFailed()"); + DBusMessage *message = NULL; + DBusConnection *connection = NULL; + DBusError error; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "InstallSpoolerFailed"); + if (message == NULL) + goto finish_error3; + + if (!dbus_connection_send (connection, message, NULL)) + { + dbus_message_unref (message); + message = NULL; + } + +finish_error3: + if(message) + dbus_message_unref (message); +} + +static void +SpoolerStartFailed () +{ + syslog (LOG_DEBUG, "SpoolerStartFailed()"); + DBusMessage *message = NULL; + DBusConnection *connection = NULL; + DBusError error; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "SpoolerStartFailed"); + if (message == NULL) + goto finish_error4; + + if (!dbus_connection_send (connection, message, NULL)) + { + dbus_message_unref (message); + message = NULL; + } + +finish_error4: + if(message) + dbus_message_unref (message); +} + +dbus_bool_t +InstallSpooler () +{ + syslog (LOG_DEBUG, "InstallSpooler()"); + DBusMessage *message = NULL; + DBusMessage *reply = NULL; + DBusPendingCall *pending_call = NULL; + DBusConnection *connection = NULL; + DBusError error; + dbus_bool_t ok = FALSE; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "InstallSpooler"); + if (message == NULL) + goto finish_error5; + + if (!dbus_connection_send_with_reply (connection, message, &pending_call, 360000)) + { + dbus_message_unref (message); + goto finish_error5; + } + + if (pending_call == NULL) + goto finish_error5; + + dbus_pending_call_block(pending_call); + + reply = dbus_pending_call_steal_reply(pending_call); + if (reply == NULL) + goto finish_error5; + + dbus_message_get_args (reply, NULL, + DBUS_TYPE_BOOLEAN, &ok, + DBUS_TYPE_INVALID); +finish_error5: + if(message) + dbus_message_unref (message); + if(reply) + dbus_message_unref (reply); + if(pending_call) + dbus_pending_call_unref (pending_call); + return ok; + +} +dbus_bool_t +CheckAndInstallDrivers () +{ + syslog (LOG_DEBUG, "CheckAndInstallDrivers()"); + DBusMessage *message = NULL; + DBusMessage *reply = NULL; + DBusPendingCall *pending_call = NULL; + DBusConnection *connection = NULL; + DBusError error; + dbus_bool_t ok = FALSE; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "CheckAndInstallDrivers"); + if (message == NULL) + goto finish_error6; + + dbus_message_append_args (message, + DBUS_TYPE_STRING, &global_make, + DBUS_TYPE_STRING, &global_model, DBUS_TYPE_INVALID); + + if (!dbus_connection_send_with_reply (connection, message, &pending_call, 360000)) + { + dbus_message_unref (message); + goto finish_error6; + } + + if (pending_call == NULL) + goto finish_error6; + + dbus_pending_call_block(pending_call); + + reply = dbus_pending_call_steal_reply(pending_call); + if (reply == NULL) + goto finish_error6; + + dbus_message_get_args (reply, NULL, + DBUS_TYPE_BOOLEAN, &ok, + DBUS_TYPE_INVALID); +finish_error6: + if(message) + dbus_message_unref (message); + if(reply) + dbus_message_unref (reply); + if(pending_call) + dbus_pending_call_unref (pending_call); + return ok; +} + +static void +MissingDriver() +{ + syslog (LOG_DEBUG, "MissingDriver()"); + DBusMessage *message = NULL; + DBusConnection *connection = NULL; + DBusError error; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "MissingDriver"); + dbus_message_append_args (message, + DBUS_TYPE_STRING, &global_make, + DBUS_TYPE_STRING, &global_model, DBUS_TYPE_INVALID); + + if (message == NULL) + goto finish_error7; + + if (!dbus_connection_send (connection, message, NULL)) + { + dbus_message_unref (message); + message = NULL; + } + +finish_error7: + if(message) + dbus_message_unref (message); +} +dbus_bool_t +CheckInstalledSpooler () +{ + syslog (LOG_DEBUG, "CheckInstalledSpooler()"); + DBusMessage *message = NULL; + DBusMessage *reply = NULL; + DBusPendingCall *pending_call = NULL; + DBusConnection *connection = NULL; + DBusError error; + dbus_bool_t ok = FALSE; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "CheckInstalledSpooler"); + if (message == NULL) + goto finish_error8; + + if (!dbus_connection_send_with_reply (connection, message, &pending_call, 360000)) + { + dbus_message_unref (message); + goto finish_error8; + } + + if (pending_call == NULL) + goto finish_error8; + + dbus_pending_call_block(pending_call); + + reply = dbus_pending_call_steal_reply(pending_call); + if (reply == NULL) + goto finish_error8; + + dbus_message_get_args (reply, NULL, + DBUS_TYPE_BOOLEAN, &ok, + DBUS_TYPE_INVALID); +finish_error8: + if(message) + dbus_message_unref (message); + if(reply) + dbus_message_unref (reply); + if(pending_call) + dbus_pending_call_unref (pending_call); + return ok; + +} +dbus_bool_t +CheckInstalledDrivers () +{ + syslog (LOG_DEBUG, "CheckInstalledDrivers()"); + DBusMessage *message = NULL; + DBusMessage *reply = NULL; + DBusPendingCall *pending_call = NULL; + DBusConnection *connection = NULL; + DBusError error; + dbus_bool_t ok = FALSE; + + dbus_error_init (&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS, + DBUS_PATH_ORG_FREEDESKTOP_DBUS, + DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, + "CheckInstalledDrivers"); + if (message == NULL) + goto finish_error9; + + dbus_message_append_args (message, + DBUS_TYPE_STRING, &global_make, + DBUS_TYPE_STRING, &global_model, DBUS_TYPE_INVALID); + + if (!dbus_connection_send_with_reply (connection, message, &pending_call, 360000)) + { + dbus_message_unref (message); + goto finish_error9; + } + + if (pending_call == NULL) + goto finish_error9; + + dbus_pending_call_block(pending_call); + + reply = dbus_pending_call_steal_reply(pending_call); + if (reply == NULL) + goto finish_error9; + + dbus_message_get_args (reply, NULL, + DBUS_TYPE_BOOLEAN, &ok, + DBUS_TYPE_INVALID); +finish_error9: + if(message) + dbus_message_unref (message); + if(reply) + dbus_message_unref (reply); + if(pending_call) + dbus_pending_call_unref (pending_call); + return ok; + +} + static int find_matching_device_uris (struct device_id *id, const char *usbserial, @@ -788,6 +1158,7 @@ find_matching_device_uris (struct device_id *id, const char *devpath, struct usb_uri_map *map) { +// syslog (LOG_DEBUG, "find_matching_device_uris()"); http_t *cups; ipp_t *request, *answer; ipp_attribute_t *attr; @@ -1146,6 +1517,7 @@ for_each_matching_queue (struct device_uris *device_uris, void *context, char *usblpdev, size_t usblpdevlen) { +// syslog (LOG_DEBUG, "for_each_matching_queue()"); size_t matched = 0; http_t *cups = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ()); @@ -1307,6 +1679,7 @@ for_each_matching_queue (struct device_uris *device_uris, static void enable_queue (const char *printer_uri, void *context) { +// syslog (LOG_DEBUG, "enable_queue()"); /* Enable it. */ http_t *cups = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ()); @@ -1329,7 +1702,10 @@ enable_queue (const char *printer_uri, void *context) if (answer->request.status.status_code > IPP_OK_CONFLICT) syslog (LOG_ERR, "IPP-Resume-Printer request failed"); else + { syslog (LOG_INFO, "Re-enabled printer %s", printer_uri); + PrinterEnabled(); + } ippDelete (answer); httpClose (cups); @@ -1370,6 +1746,7 @@ bluetooth_verify_address (const char *bdaddr) static int do_add (const char *cmd, const char *devpath) { +// syslog (LOG_DEBUG, "do_add()"); pid_t pid; int f; struct device_id id; @@ -1427,6 +1804,16 @@ do_add (const char *cmd, const char *devpath) syslog (LOG_DEBUG, "MFG:%s MDL:%s SERN:%s serial:%s", id.mfg, id.mdl, id.sern ? id.sern : "-", usbserial[0] ? usbserial : "-"); + global_make = id.mfg; + global_model = id.mdl; + CheckAndInstallDrivers(); + if(!CheckInstalledDrivers()) + { + MissingDriver(); + syslog (LOG_DEBUG, "FAIL HERE"); + exit(1); + } + if (!is_bluetooth) { find_matching_device_uris (&id, usbserial, &device_uris, usb_device_devpath, @@ -1499,6 +1886,7 @@ do_add (const char *cmd, const char *devpath) static void remove_queue (const char *printer_uri) { +// syslog (LOG_DEBUG, "remove_queue()"); /* Disable it. */ http_t *cups = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ()); @@ -1531,6 +1919,7 @@ remove_queue (const char *printer_uri) static void disable_queue (const char *printer_uri, void *context) { +// syslog (LOG_DEBUG, "disable_queue()"); /* Disable it. */ http_t *cups = httpConnectEncrypt (cupsServer (), ippPort (), cupsEncryption ()); @@ -1555,8 +1944,12 @@ disable_queue (const char *printer_uri, void *context) if (answer->request.status.status_code > IPP_OK_CONFLICT) syslog (LOG_ERR, "IPP-Pause-Printer request failed"); else + { syslog (LOG_INFO, "Disabled printer %s as the corresponding device " "was unplugged or turned off", printer_uri); + // PrinterDisabled(); + // + } ippDelete (answer); httpClose (cups); @@ -1565,6 +1958,7 @@ disable_queue (const char *printer_uri, void *context) static int do_remove (const char *devpath) { +// syslog (LOG_DEBUG, "do_remove()"); struct usb_uri_map *map; struct usb_uri_map_entry *entry, **prev; struct device_uris *uris = NULL; @@ -1610,6 +2004,7 @@ do_remove (const char *devpath) int main (int argc, char **argv) { +// syslog (LOG_DEBUG, "main()"); int add; if (argc != 3 || @@ -1625,8 +2020,39 @@ main (int argc, char **argv) openlog ("udev-configure-printer", 0, LOG_LPR); cupsSetPasswordCB (no_password); - if (add) + if (add) + { + if ( system( "rpm -q task-printing-server" ) != 0 ) + { + syslog (LOG_DEBUG, "Cups isn't installed, let's install it"); + /* + * We need to use dbus to ask the applet to install cups + */ + InstallSpooler(); + if(!CheckInstalledSpooler ()) + { + InstallSpoolerFailed(); + exit(1); + } + } + if(system("/sbin/service cups status") != 0) + { + if(system("/sbin/service cups restart") != 0) + { + SpoolerStartFailed(); + /* we cannot go ahead without cups running */ + exit(1); + } + } return do_add (argv[0], argv[2]); - - return do_remove (argv[2]); + } + else + { + // if(system("/sbin/service cups status") == 0) + // { + // /* if the cups daemon is running, notify on the desktop about the printer being disabled */ + // PrinterDisabled(); + // }*/ + return do_remove (argv[2]); + } }