]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/testlpd.c
Load cups into easysw/current.
[thirdparty/cups.git] / scheduler / testlpd.c
diff --git a/scheduler/testlpd.c b/scheduler/testlpd.c
new file mode 100644 (file)
index 0000000..a499503
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * "$Id: testlpd.c 5868 2006-08-23 19:39:39Z mike $"
+ *
+ *   cups-lpd test program for the Common UNIX Printing System (CUPS).
+ *
+ *   Copyright 2006 by Easy Software Products, all rights reserved.
+ *
+ *   These coded instructions, statements, and computer programs are the
+ *   property of Easy Software Products and are protected by Federal
+ *   copyright law.  Distribution and use rights are outlined in the file
+ *   "LICENSE.txt" which should have been included with this file.  If this
+ *   file is missing or damaged please contact Easy Software Products
+ *   at:
+ *
+ *       Attn: CUPS Licensing Information
+ *       Easy Software Products
+ *       44141 Airport View Drive, Suite 204
+ *       Hollywood, Maryland 20636 USA
+ *
+ *       Voice: (301) 373-9600
+ *       EMail: cups-info@cups.org
+ *         WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ *   main()          - Simulate an LPD client.
+ *   do_command()    - Send the LPD command and wait for a response.
+ *   print_job()     - Submit a file for printing.
+ *   print_waiting() - Print waiting jobs.
+ *   remove_job()    - Cancel a print job.
+ *   status_long()   - Show the long printer status.
+ *   status_short()  - Show the short printer status.
+ *   usage()         - Show program usage...
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int     do_command(int outfd, int infd, const char *command);
+static int     print_job(int outfd, int infd, char *dest, char **args);
+static int     print_waiting(int outfd, int infd, char *dest);
+static int     remove_job(int outfd, int infd, char *dest, char **args);
+static int     status_long(int outfd, int infd, char *dest, char **args);
+static int     status_short(int outfd, int infd, char *dest, char **args);
+static void    usage(void);
+
+
+/*
+ * 'main()' - Simulate an LPD client.
+ */
+
+int                                    /* O - Exit status */
+main(int  argc,                                /* I - Number of command-line arguments */
+     char *argv[])                     /* I - Command-line arguments */
+{
+  int  i;                              /* Looping var */
+  int  status;                         /* Test status */
+  char *op,                            /* Operation to test */
+       **opargs,                       /* Remaining arguments */
+       *dest;                          /* Destination */
+  int  cupslpd_argc;                   /* Argument count for cups-lpd */
+  char *cupslpd_argv[1000];            /* Arguments for cups-lpd */
+  int  cupslpd_stdin[2],               /* Standard input for cups-lpd */
+       cupslpd_stdout[2],              /* Standard output for cups-lpd */
+       cupslpd_pid;                    /* Process ID for cups-lpd */
+
+
+ /*
+  * Collect command-line arguments...
+  */
+
+  op              = NULL;
+  opargs          = NULL;
+  dest            = NULL;
+  cupslpd_argc    = 1;
+  cupslpd_argv[0] = (char *)"cups-lpd";
+
+  for (i = 1; i < argc; i ++)
+    if (!strncmp(argv[i], "-o", 2))
+    {
+      cupslpd_argv[cupslpd_argc++] = argv[i];
+
+      if (argv[i][2])
+      {
+        i ++;
+
+       if (i >= argc)
+         usage();
+
+       cupslpd_argv[cupslpd_argc++] = argv[i];
+      }
+    }
+    else if (argv[i][0] == '-')
+      usage();
+    else if (!op)
+      op = argv[i];
+    else if (!dest)
+      dest = argv[i];
+    else
+    {
+      opargs = argv + i;
+      break;
+    }
+
+  if (!op ||
+      (!strcmp(op, "print-job") && (!dest || !opargs)) ||
+      (!strcmp(op, "remove-job") && (!dest || !opargs)) ||
+      (strcmp(op, "print-job") && strcmp(op, "print-waiting") &&
+       strcmp(op, "remove-job") && strcmp(op, "status-long") &&
+       strcmp(op, "status-short")))
+    usage();
+
+ /*
+  * Run the cups-lpd program using pipes...
+  */
+
+  cupslpd_argv[cupslpd_argc] = NULL;
+
+  pipe(cupslpd_stdin);
+  pipe(cupslpd_stdout);
+
+  if ((cupslpd_pid = fork()) < 0)
+  {
+   /*
+    * Error!
+    */
+
+    perror("testlpd: Unable to fork");
+    return (1);
+  }
+  else if (cupslpd_pid == 0)
+  {
+   /*
+    * Child goes here...
+    */
+
+    close(0);
+    dup(cupslpd_stdin[0]);
+    close(cupslpd_stdin[0]);
+    close(cupslpd_stdin[1]);
+
+    close(1);
+    dup(cupslpd_stdout[1]);
+    close(cupslpd_stdout[0]);
+    close(cupslpd_stdout[1]);
+
+    execv("./cups-lpd", cupslpd_argv);
+
+    perror("testlpd: Unable to exec ./cups-lpd");
+    exit(errno);
+  }
+  else
+  {
+    close(cupslpd_stdin[0]);
+    close(cupslpd_stdout[1]);
+  }
+
+ /*
+  * Do the operation test...
+  */
+
+  if (!strcmp(op, "print-job"))
+    status = print_job(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
+  else if (!strcmp(op, "print-waiting"))
+    status = print_waiting(cupslpd_stdin[1], cupslpd_stdout[0], dest);
+  else if (!strcmp(op, "remove-job"))
+    status = remove_job(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
+  else if (!strcmp(op, "status-long"))
+    status = status_long(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
+  else if (!strcmp(op, "status-short"))
+    status = status_short(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
+
+ /*
+  * Kill the test program...
+  */
+
+  close(cupslpd_stdin[1]);
+  close(cupslpd_stdout[0]);
+  kill(cupslpd_pid, SIGTERM);
+
+ /*
+  * Return the test status...
+  */
+
+  return (status);
+}
+
+
+/*
+ * 'do_command()' - Send the LPD command and wait for a response.
+ */
+
+static int                             /* O - Status from cups-lpd */
+do_command(int        outfd,           /* I - Command file descriptor */
+           int        infd,            /* I - Response file descriptor */
+          const char *command)         /* I - Command line to send */
+{
+  int  len;                            /* Length of command line */
+  char status;                         /* Status byte */
+
+
+  printf("COMMAND: %02X %s", command[0], command + 1);
+
+  len = strlen(command);
+
+  if (write(outfd, command, len) < len)
+  {
+    puts("    Write failed!");
+    return (-1);
+  }
+
+  if (read(infd, &status, 1) < 1)
+    puts("IN: ERROR");
+  else
+    printf("IN: %d\n", status);
+
+  return (status);
+}
+
+
+/*
+ * 'print_job()' - Submit a file for printing.
+ */
+
+static int                             /* O - Status from cups-lpd */
+print_job(int  outfd,                  /* I - Command file descriptor */
+          int  infd,                   /* I - Response file descriptor */
+         char *dest,                   /* I - Destination */
+         char **args)                  /* I - Arguments */
+{
+  int          fd;                     /* Print file descriptor */
+  char         command[1024],          /* Command buffer */
+               control[1024],          /* Control file */
+               buffer[8192];           /* Print buffer */
+  int          status;                 /* Status of command */
+  struct stat  fileinfo;               /* File information */
+  char         *jobname;               /* Job name */
+  int          sequence;               /* Sequence number */
+  int          bytes;                  /* Bytes read/written */
+
+
+ /*
+  * Check the print file...
+  */
+
+  if (stat(args[0], &fileinfo))
+  {
+    perror(args[0]);
+    return (-1);
+  }
+
+  if ((fd = open(args[0], O_RDONLY)) < 0)
+  {
+    perror(args[0]);
+    return (-1);
+  }
+
+ /*
+  * Send the "receive print job" command...
+  */
+
+  snprintf(command, sizeof(command), "\002%s\n", dest);
+  if ((status = do_command(outfd, infd, command)) != 0)
+  {
+    close(fd);
+    return (status);
+  }
+
+ /*
+  * Format a control file string that will be used to submit the job...
+  */
+
+  if ((jobname = strrchr(args[0], '/')) != NULL)
+    jobname ++;
+  else
+    jobname = args[0];
+
+  sequence = (int)getpid() % 1000;
+
+  snprintf(control, sizeof(control),
+           "Hlocalhost\n"
+           "P%s\n"
+           "J%s\n"
+           "ldfA%03.3dlocalhost\n"
+           "UdfA%03.3dlocalhost\n"
+           "N%s\n",
+          cupsUser(), jobname, sequence, sequence, jobname);
+
+ /*
+  * Send the control file...
+  */
+
+  bytes = strlen(control);
+
+  snprintf(command, sizeof(command), "\002%d cfA%03.3dlocalhost\n",
+           bytes, sequence);
+
+  if ((status = do_command(outfd, infd, command)) != 0)
+  {
+    close(fd);
+    return (status);
+  }
+
+  bytes ++;
+
+  if (write(outfd, control, bytes) < bytes)
+  {
+    printf("CONTROL: Unable to write %d bytes!\n", bytes);
+    close(fd);
+    return (-1);
+  }
+
+  printf("CONTROL: Wrote %d bytes.\n", bytes);
+
+  if (read(infd, command, 1) < 1)
+  {
+    puts("IN: ERROR");
+    close(fd);
+    return (-1);
+  }
+  else
+  {
+    status = command[0];
+
+    printf("IN: %d\n", status);
+  }
+
+ /*
+  * Send the data file...
+  */
+
+  snprintf(command, sizeof(command), "\003%d dfA%03.3dlocalhost\n",
+           (int)fileinfo.st_size, sequence);
+
+  if ((status = do_command(outfd, infd, command)) != 0)
+  {
+    close(fd);
+    return (status);
+  }
+
+  while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
+  {
+    if (write(outfd, buffer, bytes) < bytes)
+    {
+      printf("DATA: Unable to write %d bytes!\n", bytes);
+      close(fd);
+      return (-1);
+    }
+  }
+
+  write(outfd, "", 1);
+
+  close(fd);
+
+  printf("DATA: Wrote %d bytes.\n", (int)fileinfo.st_size);
+
+  if (read(infd, command, 1) < 1)
+  {
+    puts("IN: ERROR");
+    close(fd);
+    return (-1);
+  }
+  else
+  {
+    status = command[0];
+
+    printf("IN: %d\n", status);
+  }
+
+  return (status);
+}
+
+
+/*
+ * 'print_waiting()' - Print waiting jobs.
+ */
+
+static int                             /* O - Status from cups-lpd */
+print_waiting(int  outfd,              /* I - Command file descriptor */
+              int  infd,               /* I - Response file descriptor */
+             char *dest)               /* I - Destination */
+{
+  char         command[1024];          /* Command buffer */
+
+
+ /*
+  * Send the "print waiting jobs" command...
+  */
+
+  snprintf(command, sizeof(command), "\001%s\n", dest);
+
+  return (do_command(outfd, infd, command));
+}
+
+
+/*
+ * 'remove_job()' - Cancel a print job.
+ */
+
+static int                             /* O - Status from cups-lpd */
+remove_job(int  outfd,                 /* I - Command file descriptor */
+           int  infd,                  /* I - Response file descriptor */
+          char *dest,                  /* I - Destination */
+          char **args)                 /* I - Arguments */
+{
+  int          i;                      /* Looping var */
+  char         command[1024];          /* Command buffer */
+
+ /*
+  * Send the "remove jobs" command...
+  */
+
+  snprintf(command, sizeof(command), "\005%s", dest);
+
+  for (i = 0; args[i]; i ++)
+  {
+    strlcat(command, " ", sizeof(command));
+    strlcat(command, args[i], sizeof(command));
+  }
+
+  strlcat(command, "\n", sizeof(command));
+
+  return (do_command(outfd, infd, command));
+}
+
+
+/*
+ * 'status_long()' - Show the long printer status.
+ */
+
+static int                             /* O - Status from cups-lpd */
+status_long(int  outfd,                        /* I - Command file descriptor */
+            int  infd,                 /* I - Response file descriptor */
+           char *dest,                 /* I - Destination */
+           char **args)                /* I - Arguments */
+{
+  char         command[1024],          /* Command buffer */
+               buffer[8192];           /* Status buffer */
+  int          bytes;                  /* Bytes read/written */
+
+
+ /*
+  * Send the "send short status" command...
+  */
+
+  if (args)
+    snprintf(command, sizeof(command), "\004%s %s\n", dest, args[0]);
+  else
+    snprintf(command, sizeof(command), "\004%s\n", dest);
+
+  bytes = strlen(command);
+
+  if (write(outfd, command, bytes) < bytes)
+    return (-1);
+
+ /*
+  * Read the status back...
+  */
+
+  while ((bytes = read(infd, buffer, sizeof(buffer))) > 0)
+  {
+    fwrite(buffer, 1, bytes, stdout);
+    fflush(stdout);
+  }
+
+  return (0);
+}
+
+
+/*
+ * 'status_short()' - Show the short printer status.
+ */
+
+static int                             /* O - Status from cups-lpd */
+status_short(int  outfd,               /* I - Command file descriptor */
+             int  infd,                        /* I - Response file descriptor */
+            char *dest,                /* I - Destination */
+            char **args)               /* I - Arguments */
+{
+  char         command[1024],          /* Command buffer */
+               buffer[8192];           /* Status buffer */
+  int          bytes;                  /* Bytes read/written */
+
+
+ /*
+  * Send the "send short status" command...
+  */
+
+  if (args)
+    snprintf(command, sizeof(command), "\003%s %s\n", dest, args[0]);
+  else
+    snprintf(command, sizeof(command), "\003%s\n", dest);
+
+  bytes = strlen(command);
+
+  if (write(outfd, command, bytes) < bytes)
+    return (-1);
+
+ /*
+  * Read the status back...
+  */
+
+  while ((bytes = read(infd, buffer, sizeof(buffer))) > 0)
+  {
+    fwrite(buffer, 1, bytes, stdout);
+    fflush(stdout);
+  }
+
+  return (0);
+}
+
+
+/*
+ * 'usage()' - Show program usage...
+ */
+
+static void
+usage(void)
+{
+  puts("Usage: testlpd [options] print-job printer user filename [... filename]");
+  puts("       testlpd [options] print-waiting [printer or user]");
+  puts("       testlpd [options] remove-job printer [user [job-id]]");
+  puts("       testlpd [options] status-long [printer or user]");
+  puts("       testlpd [options] status-short [printer or user]");
+  puts("");
+  puts("Options:");
+  puts("    -o name=value");
+
+  exit(0);
+}
+
+
+/*
+ * End of "$Id: testlpd.c 5868 2006-08-23 19:39:39Z mike $".
+ */