]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/testbackend.c
Fix build errors on Fedora.
[thirdparty/cups.git] / backend / testbackend.c
index e0f573ccdce48254bfa245122c4174a27306648e..046fc3e30c1a2e08d395184607c18f934479abd1 100644 (file)
@@ -1,46 +1,46 @@
 /*
  * "$Id$"
  *
- *   Backend test program for the Common UNIX Printing System (CUPS).
+ * Backend test program for CUPS.
  *
- *   Copyright 2007-2009 by Apple Inc.
- *   Copyright 1997-2005 by Easy Software Products, all rights reserved.
+ * Copyright 2007-2014 by Apple Inc.
+ * Copyright 1997-2005 by Easy Software Products, all rights reserved.
  *
- *   These coded instructions, statements, and computer programs are the
- *   property of Apple Inc. and are protected by Federal copyright
- *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- *   "LICENSE" which should have been included with this file.  If this
- *   file is missing or damaged, see the license at "http://www.cups.org/".
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * "LICENSE" which should have been included with this file.  If this
+ * file is missing or damaged, see the license at "http://www.cups.org/".
  *
- *   This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- *   main()    - Run the named backend.
- *   usage()   - Show usage information.
- *   walk_cb() - Show results of cupsSideChannelSNMPWalk...
+ * This file is subject to the Apple OS-Developed Software exception.
  */
 
 /*
  * Include necessary headers.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <cups/string.h>
+#include <cups/string-private.h>
 #include <cups/cups.h>
 #include <cups/sidechannel.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <errno.h>
 #include <sys/wait.h>
+#include <signal.h>
+
+
+/*
+ * Local globals...
+ */
+
+static int     job_canceled = 0;
 
 
 /*
  * Local functions...
  */
 
-static void    usage(void);
+static void    sigterm_handler(int sig);
+static void    usage(void) __attribute__((noreturn));
 static void    walk_cb(const char *oid, const char *data, int datalen,
                        void *context);
 
@@ -50,7 +50,7 @@ static void   walk_cb(const char *oid, const char *data, int datalen,
  *
  * Usage:
  *
- *    betest [-s] [-t] device-uri job-id user title copies options [file]
+ *    testbackend [-s] [-t] device-uri job-id user title copies options [file]
  */
 
 int                                    /* O - Exit status */
@@ -58,7 +58,9 @@ main(int  argc,                               /* I - Number of command-line args */
      char *argv[])                     /* I - Command-line arguments */
 {
   int          first_arg,              /* First argument for backend */
-               do_query = 0,           /* Do PostScript query? */
+               do_cancel = 0,          /* Simulate a cancel-job via SIGTERM */
+               do_ps = 0,              /* Do PostScript query+test? */
+               do_pcl = 0,             /* Do PCL query+test? */
                do_side_tests = 0,      /* Test side-channel ops? */
                do_trickle = 0,         /* Trickle data to backend */
                do_walk = 0,            /* Do OID lookup (0) or walking (1) */
@@ -66,15 +68,43 @@ main(int  argc,                             /* I - Number of command-line args */
   const char   *oid = ".1.3.6.1.2.1.43.10.2.1.4.1.1";
                                        /* OID to lookup or walk */
   char         scheme[255],            /* Scheme in URI == backend */
-               backend[1024];          /* Backend path */
+               backend[1024],          /* Backend path */
+               libpath[1024],          /* Path for libcups */
+               *ptr;                   /* Pointer into path */
   const char   *serverbin;             /* CUPS_SERVERBIN environment variable */
-  int          back_fds[2],            /* Back-channel pipe */
+  int          fd,                     /* Temporary file descriptor */
+               back_fds[2],            /* Back-channel pipe */
                side_fds[2],            /* Side-channel socket */
                data_fds[2],            /* Data pipe */
+               back_pid = -1,          /* Backend process ID */
+               data_pid = -1,          /* Trickle process ID */
                pid,                    /* Process ID */
                status;                 /* Exit status */
 
 
+ /*
+  * Get the current directory and point the run-time linker at the "cups"
+  * subdirectory...
+  */
+
+  if (getcwd(libpath, sizeof(libpath)) &&
+      (ptr = strrchr(libpath, '/')) != NULL && !strcmp(ptr, "/backend"))
+  {
+    strlcpy(ptr, "/cups", sizeof(libpath) - (size_t)(ptr - libpath));
+    if (!access(libpath, 0))
+    {
+#ifdef __APPLE__
+      fprintf(stderr, "Setting DYLD_LIBRARY_PATH to \"%s\".\n", libpath);
+      setenv("DYLD_LIBRARY_PATH", libpath, 1);
+#else
+      fprintf(stderr, "Setting LD_LIBRARY_PATH to \"%s\".\n", libpath);
+      setenv("LD_LIBRARY_PATH", libpath, 1);
+#endif /* __APPLE__ */
+    }
+    else
+      perror(libpath);
+  }
+
  /*
   * See if we have side-channel tests to do...
   */
@@ -84,8 +114,12 @@ main(int  argc,                             /* I - Number of command-line args */
        first_arg ++)
     if (!strcmp(argv[first_arg], "-d"))
       show_log = 1;
+    else if (!strcmp(argv[first_arg], "-cancel"))
+      do_cancel = 1;
+    else if (!strcmp(argv[first_arg], "-pcl"))
+      do_pcl = 1;
     else if (!strcmp(argv[first_arg], "-ps"))
-      do_query = 1;
+      do_ps = 1;
     else if (!strcmp(argv[first_arg], "-s"))
       do_side_tests = 1;
     else if (!strcmp(argv[first_arg], "-t"))
@@ -157,33 +191,44 @@ main(int  argc,                           /* I - Number of command-line args */
   * Execute the trickle process as needed...
   */
 
-  if (do_trickle || do_query)
+  if (do_trickle || do_pcl || do_ps || do_cancel)
   {
     pipe(data_fds);
 
-    if ((pid = fork()) == 0)
+    signal(SIGTERM, sigterm_handler);
+
+    if ((data_pid = fork()) == 0)
     {
      /*
-      * Trickle/query child comes here...  Rearrange file descriptors so that
-      * FD 
+      * Trickle/query child comes here.  Rearrange file descriptors so that
+      * FD 1, 3, and 4 point to the backend...
       */
 
-      close(0);
-      open("/dev/null", O_RDONLY);
+      if ((fd = open("/dev/null", O_RDONLY)) != 0)
+      {
+        dup2(fd, 0);
+       close(fd);
+      }
 
-      close(1);
-      dup(data_fds[1]);
+      if (data_fds[1] != 1)
+      {
+        dup2(data_fds[1], 1);
+       close(data_fds[1]);
+      }
       close(data_fds[0]);
-      close(data_fds[1]);
 
-      close(3);
-      dup(back_fds[0]);
-      close(back_fds[0]);
+      if (back_fds[0] != 3)
+      {
+        dup2(back_fds[0], 3);
+        close(back_fds[0]);
+      }
       close(back_fds[1]);
 
-      close(4);
-      dup(side_fds[0]);
-      close(side_fds[0]);
+      if (side_fds[0] != 4)
+      {
+        dup2(side_fds[0], 4);
+        close(side_fds[0]);
+      }
       close(side_fds[1]);
 
       if (do_trickle)
@@ -200,15 +245,119 @@ main(int  argc,                          /* I - Number of command-line args */
          sleep(1);
        }
       }
-      else
+      else if (do_cancel)
       {
        /*
-        * Do a simple PostScript query job to get the default page size.
+        * Write PS or PCL lines until we see SIGTERM...
        */
 
-        char   buffer[1024];           /* Buffer for response data */
+        int    line = 0, page = 0;     /* Current line and page */
        ssize_t bytes;                  /* Number of bytes of response data */
-        static const char *ps_query =  /* PostScript query file */
+       char    buffer[1024];           /* Output buffer */
+
+
+        if (do_pcl)
+         write(1, "\033E", 2);
+       else
+         write(1, "%!\n/Courier findfont 12 scalefont setfont 0 setgray\n", 52);
+
+        while (!job_canceled)
+       {
+         if (line == 0)
+         {
+           page ++;
+
+           if (do_pcl)
+             snprintf(buffer, sizeof(buffer), "PCL Page %d\r\n\r\n", page);
+           else
+             snprintf(buffer, sizeof(buffer),
+                      "18 732 moveto (PS Page %d) show\n", page);
+
+           write(1, buffer, strlen(buffer));
+         }
+
+          line ++;
+
+         if (do_pcl)
+           snprintf(buffer, sizeof(buffer), "Line %d\r\n", line);
+         else
+           snprintf(buffer, sizeof(buffer), "18 %d moveto (Line %d) show\n",
+                    720 - line * 12, line);
+
+         write(1, buffer, strlen(buffer));
+
+          if (line >= 55)
+         {
+          /*
+           * Eject after 55 lines...
+           */
+
+           line = 0;
+           if (do_pcl)
+             write(1, "\014", 1);
+           else
+             write(1, "showpage\n", 9);
+         }
+
+        /*
+         * Check for back-channel data...
+         */
+
+         if ((bytes = cupsBackChannelRead(buffer, sizeof(buffer), 0)) > 0)
+           write(2, buffer, (size_t)bytes);
+
+        /*
+         * Throttle output to ~100hz...
+         */
+
+         usleep(10000);
+       }
+
+       /*
+        * Eject current page with info...
+       */
+
+        if (do_pcl)
+         snprintf(buffer, sizeof(buffer),
+                  "Canceled on line %d of page %d\r\n\014\033E", line, page);
+       else
+         snprintf(buffer, sizeof(buffer),
+                  "\n18 %d moveto (Canceled on line %d of page %d)\nshowpage\n",
+                  720 - line * 12, line, page);
+
+       write(1, buffer, strlen(buffer));
+
+       /*
+        * See if we get any back-channel data...
+       */
+
+        while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer), 5.0)) > 0)
+         write(2, buffer, (size_t)bytes);
+
+       exit(0);
+      }
+      else
+      {
+       /*
+        * Do PS or PCL query + test pages.
+       */
+
+        char           buffer[1024];   /* Buffer for response data */
+       ssize_t         bytes;          /* Number of bytes of response data */
+       double          timeout;        /* Timeout */
+       const char      *data;          /* Data to send */
+        static const char *pcl_data =  /* PCL data */
+               "\033%-12345X@PJL\r\n"
+               "@PJL JOB NAME = \"Hello, World!\"\r\n"
+               "@PJL INFO USTATUS\r\n"
+               "@PJL ENTER LANGUAGE = PCL\r\n"
+               "\033E"
+               "Hello, World!\n"
+               "\014"
+               "\033%-12345X@PJL\r\n"
+               "@PJL EOJ NAME=\"Hello, World!\"\r\n"
+               "\033%-12345X";
+        static const char *ps_data =   /* PostScript data */
                "%!\n"
                "save\n"
                "product = flush\n"
@@ -240,20 +389,33 @@ main(int  argc,                           /* I - Number of command-line args */
                "  {exch pop exit} {pop} ifelse\n"
                "} bind forall\n"
                "= flush pop pop\n"
+               "/Courier findfont 12 scalefont setfont\n"
+               "0 setgray 36 720 moveto (Hello, ) show product show (!) show\n"
+               "showpage\n"
                "restore\n"
                "\004";
 
 
-        write(1, ps_query, strlen(ps_query));
+       if (do_pcl)
+         data = pcl_data;
+       else
+         data = ps_data;
+
+        write(1, data, strlen(data));
        write(2, "DEBUG: START\n", 13);
-        while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer), 5.0)) > 0)
-         write(2, buffer, bytes);
+       timeout = 60.0;
+        while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer),
+                                           timeout)) > 0)
+       {
+         write(2, buffer, (size_t)bytes);
+         timeout = 5.0;
+       }
        write(2, "\nDEBUG: END\n", 12);
       }
 
       exit(0);
     }
-    else if (pid < 0)
+    else if (data_pid < 0)
     {
       perror("testbackend: Unable to fork");
       return (1);
@@ -266,42 +428,51 @@ main(int  argc,                           /* I - Number of command-line args */
   * Execute the backend...
   */
 
-  if ((pid = fork()) == 0)
+  if ((back_pid = fork()) == 0)
   {
    /*
     * Child comes here...
     */
 
-    if (do_trickle || do_query)
+    if (do_trickle || do_ps || do_pcl || do_cancel)
     {
-      close(0);
-      dup(data_fds[0]);
-      close(data_fds[0]);
+      if (data_fds[0] != 0)
+      {
+        dup2(data_fds[0], 0);
+        close(data_fds[0]);
+      }
       close(data_fds[1]);
     }
 
     if (!show_log)
     {
-      close(2);
-      open("/dev/null", O_WRONLY);
+      if ((fd = open("/dev/null", O_WRONLY)) != 2)
+      {
+        dup2(fd, 2);
+       close(fd);
+      }
     }
 
-    close(3);
-    dup(back_fds[1]);
-    close(back_fds[0]);
+    if (back_fds[1] != 3)
+    {
+      dup2(back_fds[1], 3);
+      close(back_fds[0]);
+    }
     close(back_fds[1]);
 
-    close(4);
-    dup(side_fds[1]);
-    close(side_fds[0]);
+    if (side_fds[1] != 4)
+    {
+      dup2(side_fds[1], 4);
+      close(side_fds[0]);
+    }
     close(side_fds[1]);
 
     execv(backend, argv + first_arg);
-    fprintf(stderr, "textbackend: Unable to execute \"%s\": %s\n", backend,
+    fprintf(stderr, "testbackend: Unable to execute \"%s\": %s\n", backend,
             strerror(errno));
     return (errno);
   }
-  else if (pid < 0)
+  else if (back_pid < 0)
   {
     perror("testbackend: Unable to fork");
     return (1);
@@ -311,20 +482,24 @@ main(int  argc,                           /* I - Number of command-line args */
   * Parent comes here, setup back and side channel file descriptors...
   */
 
-  if (do_trickle || do_query)
+  if (do_trickle || do_ps || do_pcl || do_cancel)
   {
     close(data_fds[0]);
     close(data_fds[1]);
   }
 
-  close(3);
-  dup(back_fds[0]);
-  close(back_fds[0]);
+  if (back_fds[0] != 3)
+  {
+    dup2(back_fds[0], 3);
+    close(back_fds[0]);
+  }
   close(back_fds[1]);
 
-  close(4);
-  dup(side_fds[0]);
-  close(side_fds[0]);
+  if (side_fds[0] != 4)
+  {
+    dup2(side_fds[0], 4);
+    close(side_fds[0]);
+  }
   close(side_fds[1]);
 
  /*
@@ -353,7 +528,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
     length   = 0;
     scstatus = cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer,
-                                        &length, 5.0);
+                                        &length, 60.0);
     printf("CUPS_SC_CMD_DRAIN_OUTPUT returned %s\n", statuses[scstatus]);
 
     length   = 1;
@@ -391,13 +566,13 @@ main(int  argc,                           /* I - Number of command-line args */
 
       length   = sizeof(buffer);
       scstatus = cupsSideChannelSNMPGet(oid, buffer, &length, 5.0);
-      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %s\n", oid,
-            statuses[scstatus], buffer);
+      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %d bytes (%s)\n", oid,
+            statuses[scstatus], (int)length, buffer);
 
       length   = sizeof(buffer);
       scstatus = cupsSideChannelSNMPGet(oid, buffer, &length, 5.0);
-      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %s\n", oid,
-            statuses[scstatus], buffer);
+      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %d bytes (%s)\n", oid,
+            statuses[scstatus], (int)length, buffer);
     }
 
     length   = 0;
@@ -406,14 +581,26 @@ main(int  argc,                           /* I - Number of command-line args */
     printf("CUPS_SC_CMD_SOFT_RESET returned %s\n", statuses[scstatus]);
   }
 
-  while (wait(&status) != pid);
+  if (do_cancel)
+  {
+    sleep(1);
+    kill(data_pid, SIGTERM);
+    kill(back_pid, SIGTERM);
+  }
 
-  if (status)
+  while ((pid = wait(&status)) > 0)
   {
-    if (WIFEXITED(status))
-      printf("%s exited with status %d!\n", backend, WEXITSTATUS(status));
-    else
-      printf("%s crashed with signal %d!\n", backend, WTERMSIG(status));
+    if (status)
+    {
+      if (WIFEXITED(status))
+       printf("%s exited with status %d!\n",
+              pid == back_pid ? backend : "test",
+              WEXITSTATUS(status));
+      else
+       printf("%s crashed with signal %d!\n",
+              pid == back_pid ? backend : "test",
+              WTERMSIG(status));
+    }
   }
 
  /*
@@ -424,6 +611,19 @@ main(int  argc,                            /* I - Number of command-line args */
 }
 
 
+/*
+ * 'sigterm_handler()' - Flag when we get SIGTERM.
+ */
+
+static void
+sigterm_handler(int sig)               /* I - Signal */
+{
+  (void)sig;
+
+  job_canceled = 1;
+}
+
+
 /*
  * 'usage()' - Show usage information.
  */
@@ -431,16 +631,20 @@ main(int  argc,                           /* I - Number of command-line args */
 static void
 usage(void)
 {
-  puts("Usage: testbackend [-d] [-ps] [-s [-oid OID] [-walk OID]] [-t] "
-       "device-uri job-id user title copies options [file]");
+  puts("Usage: testbackend [-cancel] [-d] [-ps | -pcl] [-s [-get OID] "
+       "[-walk OID]] [-t] device-uri job-id user title copies options [file]");
   puts("");
   puts("Options:");
+  puts("  -cancel     Simulate a canceled print job after 2 seconds.");
   puts("  -d          Show log messages from backend.");
-  puts("  -oid OID    Lookup the specified SNMP OID.");
-  puts("  -ps         Send PostScript query code to backend.");
-  puts("  -s          Do SNMP tests.");
+  puts("  -get OID    Lookup the specified SNMP OID.");
+  puts("              (.1.3.6.1.2.1.43.10.2.1.4.1.1 is a good one for printers)");
+  puts("  -pcl        Send PCL+PJL query and test page to backend.");
+  puts("  -ps         Send PostScript query and test page to backend.");
+  puts("  -s          Do side-channel + SNMP tests.");
   puts("  -t          Send spaces slowly to backend ('trickle').");
   puts("  -walk OID   Walk the specified SNMP OID.");
+  puts("              (.1.3.6.1.2.1.43 is a good one for printers)");
 
   exit(1);
 }
@@ -456,7 +660,22 @@ walk_cb(const char *oid,           /* I - OID */
        int        datalen,             /* I - Length of data */
        void       *context)            /* I - Context (unused) */
 {
-  printf("CUPS_SC_CMD_SNMP_WALK %s=%s (%d bytes)\n", oid, data, datalen);
+  char temp[80];
+
+  (void)context;
+
+  if ((size_t)datalen > (sizeof(temp) - 1))
+  {
+    memcpy(temp, data, sizeof(temp) - 1);
+    temp[sizeof(temp) - 1] = '\0';
+  }
+  else
+  {
+    memcpy(temp, data, (size_t)datalen);
+    temp[datalen] = '\0';
+  }
+
+  printf("CUPS_SC_CMD_SNMP_WALK %s, %d bytes (%s)\n", oid, datalen, temp);
 }