トップ 最新 追記

Masa's blog

検索キーワード:

2017年04月30日 firefox-53 with cairo-gtk3 and lprng [長年日記]

_ firefox-53 with cairo-gtk3 and lprng

I tried to build firefox-53, but it failed. because firefox-53 already doesn't support cailo-gtk2 ! Of course, I have succeeded to build firefox-53 with cairo-gtk3.

But I faced to another issue about printing by firefox. gtk2 supports printing by lpr, but gtk3 doesn't support it. And I have been LPRng's user in long time :P

CUPS is one of solutions for this issue, but I don't like it. So I resolved this issue by another way ;)

notify_change.c

#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>

/* Read all available inotify events from the file descriptor 'fd'.
   wd is the table of watch descriptors for the directories in argv.
   argc is the length of wd and argv.
   argv is the list of watched directories.
   Entry 0 of wd and argv is unused. */

static void handle_events(int fd, int *wd, int argc, char *argv[])
{
    /* Some systems cannot read integer variables if they are not
       properly aligned. On other systems, incorrect alignment may
       decrease performance. Hence, the buffer used for reading from
       the inotify file descriptor should have the same alignment as
       struct inotify_event. */

    char buf[4096]
        __attribute__ ((aligned(__alignof__(struct inotify_event))));
    const struct inotify_event *event;
    int i;
    ssize_t len;
    char *ptr;

    /* Loop while events can be read from inotify file descriptor. */

    for (;;) {

        /* Read some events. */

        len = read(fd, buf, sizeof buf);
        if (len == -1 && errno != EAGAIN) {
            perror("read");
            exit(EXIT_FAILURE);
        }

        /* If the nonblocking read() found no events to read, then
           it returns -1 with errno set to EAGAIN. In that case,
           we exit the loop. */

        if (len <= 0)
            break;

        for (ptr = buf; ptr < buf + len;
             ptr += sizeof(struct inotify_event) + event->len) {

            event = (const struct inotify_event *) ptr;

            /* Print event type */

            if (event->mask & IN_OPEN)
                printf("IN_OPEN: ");
            if (event->mask & IN_CLOSE_NOWRITE)
                printf("IN_CLOSE_NOWRITE: ");
            if (event->mask & IN_CLOSE_WRITE)
                printf("IN_CLOSE_WRITE: ");

            /* Print the name of the watched directory */

            for (i = 1; i < argc; ++i) {
                if (wd[i] == event->wd) {
                    printf("%s/", argv[i]);
                    break;
                }
            }

            /* Print the name of the file */

            if (event->len)
                printf("%s", event->name);

            /* Print type of filesystem object */

            if (event->mask & IN_ISDIR)
                printf(" [directory]\n");
            else
                printf(" [file]\n");

            fflush(stdout);
        }
    }
}

int main(int argc, char *argv[])
{
    char buf;
    int fd, i;
    int *wd;

    if (argc < 2) {
        printf("Usage: %s PATH [PATH ...]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    /* Create the file descriptor for accessing the inotify API */

    fd = inotify_init();
    if (fd == -1) {
        perror("inotify_init");
        exit(EXIT_FAILURE);
    }

    /* Allocate memory for watch descriptors */

    wd = calloc(argc, sizeof(int));
    if (wd == NULL) {
        perror("calloc");
        exit(EXIT_FAILURE);
    }

    /* Mark directories for events
       - file was opened
       - file was closed */

    for (i = 1; i < argc; i++) {
        wd[i] = inotify_add_watch(fd, argv[i], IN_OPEN | IN_CLOSE);
        if (wd[i] == -1) {
            fprintf(stderr, "Cannot watch '%s'\n", argv[i]);
            perror("inotify_add_watch");
            exit(EXIT_FAILURE);
        }
    }

    while (1) {
        handle_events(fd, wd, argc, argv);
    }

    close(fd);
    free(wd);
    exit(EXIT_SUCCESS);
}

printspool.sh

#! /bin/sh
trap "rm -fr ~/printspool/LOCK.DIR; exit 0" INT TERM
mkdir ~/printspool/LOCK.DIR || exit 1
echo -n $$ >~/printspool/LOCK.DIR/pid
notify_change ~/printspool |\
while :
do
        read line
        if [ "X`echo $line | egrep 'IN_CLOSE_WRITE.*\[file\]'`" = "X" ]
        then
                :
        else
                file=`echo $line | cut -d ' ' -f 2`
                lpr $file && rm $file
        fi
done
rm -fr ~/printspool/LOCK.DIR

How to use

  • Run printspool.sh in background.
  • When you want to print from firefox, output file(postscript or pdf) into ~/printspool/ from print menu in firefox.
  • lpr will be invoked automatically to print file and after that, file will be removed.