summaryrefslogtreecommitdiff
path: root/test/any2ppm.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/any2ppm.c')
-rw-r--r--test/any2ppm.c894
1 files changed, 894 insertions, 0 deletions
diff --git a/test/any2ppm.c b/test/any2ppm.c
new file mode 100644
index 000000000..b60b4d959
--- /dev/null
+++ b/test/any2ppm.c
@@ -0,0 +1,894 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris@chris-wilson.co.uk>
+ *
+ * Contributor(s):
+ * Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Adapted from pdf2png.c:
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Kristian Høgsberg <krh@redhat.com>
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cairo.h>
+#include <cairo-script-interpreter.h>
+
+#if CAIRO_CAN_TEST_PDF_SURFACE
+#include <poppler.h>
+#endif
+
+#if CAIRO_CAN_TEST_SVG_SURFACE
+#include <librsvg/rsvg.h>
+#ifndef RSVG_CAIRO_H
+#include <librsvg/rsvg-cairo.h>
+#endif
+#endif
+
+#if CAIRO_HAS_SPECTRE
+#include <libspectre/spectre.h>
+#endif
+
+#include <errno.h>
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if HAVE_UNISTD_H && HAVE_SIGNAL_H && HAVE_SYS_STAT_H && HAVE_SYS_SOCKET_H && HAVE_SYS_POLL_H && HAVE_SYS_UN_H
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/un.h>
+
+#define SOCKET_PATH "./.any2ppm"
+#define TIMEOUT 60000 /* 60 seconds */
+
+#if HAVE_FORK
+#define CAN_RUN_AS_DAEMON 1
+#endif
+#endif
+
+#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
+
+static int
+_cairo_writen (int fd, char *buf, int len)
+{
+ while (len) {
+ int ret;
+
+ ret = write (fd, buf, len);
+ if (ret == -1) {
+ int err = errno;
+ switch (err) {
+ case EINTR:
+ case EAGAIN:
+ continue;
+ default:
+ return 0;
+ }
+ }
+ len -= ret;
+ buf += ret;
+ }
+
+ return 1;
+}
+
+static int
+_cairo_write (int fd,
+ char *buf, int maxlen, int buflen,
+ const unsigned char *src, int srclen)
+{
+ if (buflen < 0)
+ return buflen;
+
+ while (srclen) {
+ int len;
+
+ len = buflen + srclen;
+ if (len > maxlen)
+ len = maxlen;
+ len -= buflen;
+
+ memcpy (buf + buflen, src, len);
+ buflen += len;
+ srclen -= len;
+ src += len;
+
+ if (buflen == maxlen) {
+ if (! _cairo_writen (fd, buf, buflen))
+ return -1;
+
+ buflen = 0;
+ }
+ }
+
+ return buflen;
+}
+
+static const char *
+write_ppm (cairo_surface_t *surface, int fd)
+{
+ char buf[4096];
+ cairo_format_t format;
+ const char *format_str;
+ const unsigned char *data;
+ int len;
+ int width, height, stride;
+ int i, j;
+
+ data = cairo_image_surface_get_data (surface);
+ height = cairo_image_surface_get_height (surface);
+ width = cairo_image_surface_get_width (surface);
+ stride = cairo_image_surface_get_stride (surface);
+ format = cairo_image_surface_get_format (surface);
+ if (format == CAIRO_FORMAT_ARGB32) {
+ /* see if we can convert to a standard ppm type and trim a few bytes */
+ const unsigned char *alpha = data;
+ for (j = height; j--; alpha += stride) {
+ for (i = 0; i < width; i++) {
+ if ((*(unsigned int *) (alpha+4*i) & 0xff000000) != 0xff000000)
+ goto done;
+ }
+ }
+ format = CAIRO_FORMAT_RGB24;
+ done: ;
+ }
+
+ switch (format) {
+ case CAIRO_FORMAT_ARGB32:
+ /* XXX need true alpha for svg */
+ format_str = "P7";
+ break;
+ case CAIRO_FORMAT_RGB24:
+ format_str = "P6";
+ break;
+ case CAIRO_FORMAT_A8:
+ format_str = "P5";
+ break;
+ case CAIRO_FORMAT_A1:
+ case CAIRO_FORMAT_RGB16_565:
+ case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_INVALID:
+ default:
+ return "unhandled image format";
+ }
+
+ len = sprintf (buf, "%s %d %d 255\n", format_str, width, height);
+ for (j = 0; j < height; j++) {
+ const unsigned int *row = (unsigned int *) (data + stride * j);
+
+ switch ((int) format) {
+ case CAIRO_FORMAT_ARGB32:
+ len = _cairo_write (fd,
+ buf, sizeof (buf), len,
+ (unsigned char *) row, 4 * width);
+ break;
+ case CAIRO_FORMAT_RGB24:
+ for (i = 0; i < width; i++) {
+ unsigned char rgb[3];
+ unsigned int p = *row++;
+ rgb[0] = (p & 0xff0000) >> 16;
+ rgb[1] = (p & 0x00ff00) >> 8;
+ rgb[2] = (p & 0x0000ff) >> 0;
+ len = _cairo_write (fd,
+ buf, sizeof (buf), len,
+ rgb, 3);
+ }
+ break;
+ case CAIRO_FORMAT_A8:
+ len = _cairo_write (fd,
+ buf, sizeof (buf), len,
+ (unsigned char *) row, width);
+ break;
+ }
+ if (len < 0)
+ return "write failed";
+ }
+
+ if (len && ! _cairo_writen (fd, buf, len))
+ return "write failed";
+
+ return NULL;
+}
+
+static cairo_surface_t *
+_create_image (void *closure,
+ cairo_content_t content,
+ double width, double height,
+ long uid)
+{
+ cairo_surface_t **out = closure;
+ cairo_format_t format;
+ switch (content) {
+ case CAIRO_CONTENT_ALPHA:
+ format = CAIRO_FORMAT_A8;
+ break;
+ case CAIRO_CONTENT_COLOR:
+ format = CAIRO_FORMAT_RGB24;
+ break;
+ default:
+ case CAIRO_CONTENT_COLOR_ALPHA:
+ format = CAIRO_FORMAT_ARGB32;
+ break;
+ }
+ *out = cairo_image_surface_create (format, width, height);
+ return cairo_surface_reference (*out);
+}
+
+#if CAIRO_HAS_INTERPRETER
+static const char *
+_cairo_script_render_page (const char *filename,
+ cairo_surface_t **surface_out)
+{
+ cairo_script_interpreter_t *csi;
+ cairo_surface_t *surface = NULL;
+ cairo_status_t status;
+ const cairo_script_interpreter_hooks_t hooks = {
+ &surface,
+ _create_image,
+ NULL, /* surface_destroy */
+ NULL, /* context_create */
+ NULL, /* context_destroy */
+ NULL, /* show_page */
+ NULL /* copy_page */
+ };
+
+ csi = cairo_script_interpreter_create ();
+ cairo_script_interpreter_install_hooks (csi, &hooks);
+ status = cairo_script_interpreter_run (csi, filename);
+ if (status) {
+ cairo_surface_destroy (surface);
+ surface = NULL;
+ }
+ status = cairo_script_interpreter_destroy (csi);
+ if (surface == NULL)
+ return "cairo-script interpreter failed";
+
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = cairo_surface_status (surface);
+ if (status) {
+ cairo_surface_destroy (surface);
+ return cairo_status_to_string (status);
+ }
+
+ *surface_out = surface;
+ return NULL;
+}
+
+static const char *
+cs_convert (char **argv, int fd)
+{
+ const char *err;
+ cairo_surface_t *surface = NULL; /* silence compiler warning */
+
+ err = _cairo_script_render_page (argv[0], &surface);
+ if (err != NULL)
+ return err;
+
+ err = write_ppm (surface, fd);
+ cairo_surface_destroy (surface);
+
+ return err;
+}
+#else
+static const char *
+cs_convert (char **argv, int fd)
+{
+ return "compiled without CairoScript support.";
+}
+#endif
+
+#if CAIRO_CAN_TEST_PDF_SURFACE
+/* adapted from pdf2png.c */
+static const char *
+_poppler_render_page (const char *filename,
+ const char *page_label,
+ cairo_surface_t **surface_out)
+{
+ PopplerDocument *document;
+ PopplerPage *page;
+ double width, height;
+ GError *error = NULL;
+ gchar *absolute, *uri;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ cairo_status_t status;
+
+ if (g_path_is_absolute (filename)) {
+ absolute = g_strdup (filename);
+ } else {
+ gchar *dir = g_get_current_dir ();
+ absolute = g_build_filename (dir, filename, (gchar *) 0);
+ g_free (dir);
+ }
+
+ uri = g_filename_to_uri (absolute, NULL, &error);
+ g_free (absolute);
+ if (uri == NULL)
+ return error->message; /* XXX g_error_free (error) */
+
+ document = poppler_document_new_from_file (uri, NULL, &error);
+ g_free (uri);
+ if (document == NULL)
+ return error->message; /* XXX g_error_free (error) */
+
+ page = poppler_document_get_page_by_label (document, page_label);
+ g_object_unref (document);
+ if (page == NULL)
+ return "page not found";
+
+ poppler_page_get_size (page, &width, &height);
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
+ cr = cairo_create (surface);
+
+ cairo_set_source_rgb (cr, 1., 1., 1.);
+ cairo_paint (cr);
+ cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
+
+ poppler_page_render (page, cr);
+ g_object_unref (page);
+
+ cairo_pop_group_to_source (cr);
+ cairo_paint (cr);
+
+ status = cairo_status (cr);
+ cairo_destroy (cr);
+
+ if (status) {
+ cairo_surface_destroy (surface);
+ return cairo_status_to_string (status);
+ }
+
+ *surface_out = surface;
+ return NULL;
+}
+
+static const char *
+pdf_convert (char **argv, int fd)
+{
+ const char *err;
+ cairo_surface_t *surface = NULL; /* silence compiler warning */
+
+ err = _poppler_render_page (argv[0], argv[1], &surface);
+ if (err != NULL)
+ return err;
+
+ err = write_ppm (surface, fd);
+ cairo_surface_destroy (surface);
+
+ return err;
+}
+#else
+static const char *
+pdf_convert (char **argv, int fd)
+{
+ return "compiled without PDF support.";
+}
+#endif
+
+#if CAIRO_CAN_TEST_SVG_SURFACE
+static const char *
+_rsvg_render_page (const char *filename,
+ cairo_surface_t **surface_out)
+{
+ RsvgHandle *handle;
+ RsvgDimensionData dimensions;
+ GError *error = NULL;
+ cairo_surface_t *surface;
+ cairo_t *cr;
+ cairo_status_t status;
+
+ handle = rsvg_handle_new_from_file (filename, &error);
+ if (handle == NULL)
+ return error->message; /* XXX g_error_free */
+
+ rsvg_handle_get_dimensions (handle, &dimensions);
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ dimensions.width,
+ dimensions.height);
+ cr = cairo_create (surface);
+
+ rsvg_handle_render_cairo (handle, cr);
+ g_object_unref (handle);
+
+ status = cairo_status (cr);
+ cairo_destroy (cr);
+
+ if (status) {
+ cairo_surface_destroy (surface);
+ return cairo_status_to_string (status);
+ }
+
+ *surface_out = surface;
+ return NULL;
+}
+
+static const char *
+svg_convert (char **argv, int fd)
+{
+ const char *err;
+ cairo_surface_t *surface = NULL; /* silence compiler warning */
+
+ err = _rsvg_render_page (argv[0], &surface);
+ if (err != NULL)
+ return err;
+
+ err = write_ppm (surface, fd);
+ cairo_surface_destroy (surface);
+
+ return err;
+}
+#else
+static const char *
+svg_convert (char **argv, int fd)
+{
+ return "compiled without SVG support.";
+}
+#endif
+
+#if CAIRO_HAS_SPECTRE
+static const char *
+_spectre_render_page (const char *filename,
+ const char *page_label,
+ cairo_surface_t **surface_out)
+{
+ static const cairo_user_data_key_t key;
+
+ SpectreDocument *document;
+ SpectreStatus status;
+ int width, height, stride;
+ unsigned char *pixels;
+ cairo_surface_t *surface;
+
+ document = spectre_document_new ();
+ spectre_document_load (document, filename);
+ status = spectre_document_status (document);
+ if (status) {
+ spectre_document_free (document);
+ return spectre_status_to_string (status);
+ }
+
+ if (page_label) {
+ SpectrePage *page;
+ SpectreRenderContext *rc;
+
+ page = spectre_document_get_page_by_label (document, page_label);
+ spectre_document_free (document);
+ if (page == NULL)
+ return "page not found";
+
+ spectre_page_get_size (page, &width, &height);
+ rc = spectre_render_context_new ();
+ spectre_render_context_set_page_size (rc, width, height);
+ spectre_page_render (page, rc, &pixels, &stride);
+ spectre_render_context_free (rc);
+ status = spectre_page_status (page);
+ spectre_page_free (page);
+ if (status) {
+ free (pixels);
+ return spectre_status_to_string (status);
+ }
+ } else {
+ spectre_document_get_page_size (document, &width, &height);
+ spectre_document_render (document, &pixels, &stride);
+ spectre_document_free (document);
+ }
+
+ surface = cairo_image_surface_create_for_data (pixels,
+ CAIRO_FORMAT_RGB24,
+ width, height,
+ stride);
+ cairo_surface_set_user_data (surface, &key,
+ pixels, (cairo_destroy_func_t) free);
+ *surface_out = surface;
+ return NULL;
+}
+
+static const char *
+ps_convert (char **argv, int fd)
+{
+ const char *err;
+ cairo_surface_t *surface = NULL; /* silence compiler warning */
+
+ err = _spectre_render_page (argv[0], argv[1], &surface);
+ if (err != NULL)
+ return err;
+
+ err = write_ppm (surface, fd);
+ cairo_surface_destroy (surface);
+
+ return err;
+}
+#else
+static const char *
+ps_convert (char **argv, int fd)
+{
+ return "compiled without PostScript support.";
+}
+#endif
+
+static const char *
+convert (char **argv, int fd)
+{
+ static const struct converter {
+ const char *type;
+ const char *(*func) (char **, int);
+ } converters[] = {
+ { "cs", cs_convert },
+ { "pdf", pdf_convert },
+ { "ps", ps_convert },
+ { "svg", svg_convert },
+ { NULL, NULL }
+ };
+ const struct converter *converter = converters;
+ char *type;
+
+ type = strrchr (argv[0], '.');
+ if (type == NULL)
+ return "no file extension";
+ type++;
+
+ while (converter->type) {
+ if (strcmp (type, converter->type) == 0)
+ return converter->func (argv, fd);
+ converter++;
+ }
+ return "no converter";
+}
+
+#if CAN_RUN_AS_DAEMON
+static int
+_getline (int fd, char **linep, size_t *lenp)
+{
+ char *line;
+ size_t len, i;
+ ssize_t ret;
+
+ line = *linep;
+ if (line == NULL) {
+ line = malloc (1024);
+ if (line == NULL)
+ return -1;
+ line[0] = '\0';
+ len = 1024;
+ } else
+ len = *lenp;
+
+ /* XXX simple, but ugly! */
+ i = 0;
+ do {
+ if (i == len - 1) {
+ char *nline;
+
+ nline = realloc (line, len + 1024);
+ if (nline == NULL)
+ goto out;
+
+ line = nline;
+ len += 1024;
+ }
+
+ ret = read (fd, line + i, 1);
+ if (ret == -1 || ret == 0)
+ goto out;
+ } while (line[i++] != '\n');
+
+out:
+ line[i] = '\0';
+ *linep = line;
+ *lenp = len;
+ return i-1;
+}
+
+static int
+split_line (char *line, char *argv[], int max_argc)
+{
+ int i = 0;
+
+ max_argc--; /* leave one spare for the trailing NULL */
+
+ argv[i++] = line;
+ while (i < max_argc && (line = strchr (line, ' ')) != NULL) {
+ *line++ = '\0';
+ argv[i++] = line;
+ }
+
+ /* chomp the newline */
+ line = strchr (argv[i-1], '\n');
+ if (line != NULL)
+ *line = '\0';
+
+ argv[i] = NULL;
+
+ return i;
+}
+
+static int
+any2ppm_daemon_exists (void)
+{
+ struct stat st;
+ int fd;
+ char buf[80];
+ int pid;
+ int ret;
+
+ if (stat (SOCKET_PATH, &st) < 0)
+ return 0;
+
+ fd = open (SOCKET_PATH ".pid", O_RDONLY);
+ if (fd < 0)
+ return 0;
+
+ pid = 0;
+ ret = read (fd, buf, sizeof (buf) - 1);
+ if (ret > 0) {
+ buf[ret] = '\0';
+ pid = atoi (buf);
+ }
+ close (fd);
+
+ return pid > 0 && kill (pid, 0) == 0;
+}
+
+static int
+write_pid_file (void)
+{
+ int fd;
+ char buf[80];
+ int ret;
+
+ fd = open (SOCKET_PATH ".pid", O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (fd < 0)
+ return 0;
+
+ ret = sprintf (buf, "%d\n", getpid ());
+ ret = write (fd, buf, ret) == ret;
+ close (fd);
+
+ return ret;
+}
+
+static int
+open_devnull_to_fd (int want_fd, int flags)
+{
+ int error;
+ int got_fd;
+
+ close (want_fd);
+
+ got_fd = open("/dev/null", flags | O_CREAT, 0700);
+ if (got_fd == -1)
+ return -1;
+
+ error = dup2 (got_fd, want_fd);
+ close (got_fd);
+
+ return error;
+}
+
+static int
+daemonize (void)
+{
+ void (*oldhup) (int);
+
+ /* Let the parent go. */
+ switch (fork ()) {
+ case -1: return -1;
+ case 0: break;
+ default: _exit (0);
+ }
+
+ /* Become session leader. */
+ if (setsid () == -1)
+ return -1;
+
+ /* Refork to yield session leadership. */
+ oldhup = signal (SIGHUP, SIG_IGN);
+
+ switch (fork ()) { /* refork to yield session leadership. */
+ case -1: return -1;
+ case 0: break;
+ default: _exit (0);
+ }
+
+ signal (SIGHUP, oldhup);
+
+ /* Establish stdio. */
+ if (open_devnull_to_fd (0, O_RDONLY) == -1)
+ return -1;
+ if (open_devnull_to_fd (1, O_WRONLY | O_APPEND) == -1)
+ return -1;
+ if (dup2 (1, 2) == -1)
+ return -1;
+
+ return 0;
+}
+
+static const char *
+any2ppm_daemon (void)
+{
+ int timeout = TIMEOUT;
+ struct pollfd pfd;
+ int sk, fd;
+ long flags;
+ struct sockaddr_un addr;
+ char *line = NULL;
+ size_t len = 0;
+
+#ifdef SIGPIPE
+ signal (SIGPIPE, SIG_IGN);
+#endif
+
+ /* XXX racy! */
+ if (getenv ("ANY2PPM_FORCE") == NULL && any2ppm_daemon_exists ())
+ return "any2ppm daemon already running";
+
+ unlink (SOCKET_PATH);
+
+ sk = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (sk == -1)
+ return "unable to create socket";
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ strcpy (addr.sun_path, SOCKET_PATH);
+ if (bind (sk, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
+ close (sk);
+ return "unable to bind socket";
+ }
+
+ flags = fcntl (sk, F_GETFL);
+ if (flags == -1 || fcntl (sk, F_SETFL, flags | O_NONBLOCK) == -1) {
+ close (sk);
+ return "unable to set socket to non-blocking";
+ }
+
+ if (listen (sk, 5) == -1) {
+ close (sk);
+ return "unable to listen on socket";
+ }
+
+ /* ready for client connection - detach from parent/terminal */
+ if (getenv ("ANY2PPM_NODAEMON") == NULL && daemonize () == -1) {
+ close (sk);
+ return "unable to detach from parent";
+ }
+
+ if (! write_pid_file ()) {
+ close (sk);
+ return "unable to write pid file";
+ }
+
+ if (getenv ("ANY2PPM_TIMEOUT") != NULL) {
+ timeout = atoi (getenv ("ANY2PPM_TIMEOUT"));
+ if (timeout == 0)
+ timeout = -1;
+ if (timeout > 0)
+ timeout *= 1000; /* convert env (in seconds) to milliseconds */
+ }
+
+ pfd.fd = sk;
+ pfd.events = POLLIN;
+ pfd.revents = 0; /* valgrind */
+ while (poll (&pfd, 1, timeout) > 0) {
+ while ((fd = accept (sk, NULL, NULL)) != -1) {
+ if (_getline (fd, &line, &len) != -1) {
+ char *argv[10];
+
+ if (split_line (line, argv, ARRAY_LENGTH (argv)) > 0) {
+ const char *err;
+
+ err = convert (argv, fd);
+ if (err != NULL) {
+ FILE *file = fopen (".any2ppm.errors", "a");
+ if (file != NULL) {
+ fprintf (file,
+ "Failed to convert '%s': %s\n",
+ argv[0], err);
+ fclose (file);
+ }
+ }
+ }
+ }
+ close (fd);
+ }
+ }
+ close (sk);
+ unlink (SOCKET_PATH);
+ unlink (SOCKET_PATH ".pid");
+
+ free (line);
+ return NULL;
+}
+#else
+static const char *
+any2ppm_daemon (void)
+{
+ return "daemon not compiled in.";
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+ const char *err;
+
+#if CAIRO_CAN_TEST_PDF_SURFACE || CAIRO_CAN_TEST_SVG_SURFACE
+#if GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION <= 34
+ g_type_init ();
+#endif
+#endif
+
+#if CAIRO_CAN_TEST_SVG_SURFACE
+ rsvg_set_default_dpi (72.0);
+#endif
+
+#if defined(_WIN32) && !defined (__CYGWIN__)
+ _setmode (1, _O_BINARY);
+#endif
+
+ if (argc == 1)
+ err = any2ppm_daemon ();
+ else
+ err = convert (argv + 1, 1);
+ if (err != NULL) {
+ fprintf (stderr, "Failed to run converter: %s\n", err);
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}