]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - backend/serial.c
Merge changes from CUPS 1.5.1-r9875.
[thirdparty/cups.git] / backend / serial.c
index 0aa11e90ed2c170c73ea9a57add56487c93fc364..def68cb85ad4d0a22e4cb5c0a058e9add4e4ab7d 100644 (file)
@@ -1,25 +1,16 @@
 /*
- * "$Id: serial.c 6591 2007-06-21 20:35:28Z mike $"
+ * "$Id: serial.c 7647 2008-06-16 17:39:40Z mike $"
  *
- *   Serial port backend for the Common UNIX Printing System (CUPS).
+ *   Serial port backend for CUPS.
  *
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2007 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
+ *   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 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
+ *   file is missing or damaged, see the license at "http://www.cups.org/".
  *
  *   This file is subject to the Apple OS-Developed Software exception.
  *
@@ -35,6 +26,7 @@
  */
 
 #include "backend-private.h"
+#include <stdio.h>
 
 #ifdef __hpux
 #  include <sys/modem.h>
@@ -93,7 +85,7 @@
  */
 
 static void    list_devices(void);
-static void    side_cb(int print_fd, int device_fd, int use_bc);
+static int     side_cb(int print_fd, int device_fd, int use_bc);
 
 
 /*
@@ -113,12 +105,13 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
                username[255],          /* Username info (not used) */
                resource[1024],         /* Resource info (device and options) */
                *options,               /* Pointer to options */
-               name[255],              /* Name of option */
-               value[255],             /* Value of option */
-               *ptr;                   /* Pointer into name or value */
+               *name,                  /* Name of option */
+               *value,                 /* Value of option */
+               sep;                    /* Option separator */
   int          port;                   /* Port number (not used) */
   int          copies;                 /* Number of copies to print */
-  int          print_fd,               /* Print file */
+  int          side_eof = 0,           /* Saw EOF on side-channel? */
+               print_fd,               /* Print file */
                device_fd;              /* Serial device */
   int          nfds;                   /* Maximum file descriptor value + 1 */
   fd_set       input,                  /* Input set for reading */
@@ -170,8 +163,9 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
   }
   else if (argc < 6 || argc > 7)
   {
-    fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
-           argv[0]);
+    _cupsLangPrintf(stderr,
+                    _("Usage: %s job-id user title copies options [file]"),
+                   argv[0]);
     return (CUPS_BACKEND_FAILED);
   }
 
@@ -193,7 +187,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
 
     if ((print_fd = open(argv[6], O_RDONLY)) < 0)
     {
-      perror("ERROR: unable to open print file");
+      _cupsLangPrintError("ERROR", _("Unable to open print file"));
       return (CUPS_BACKEND_FAILED);
     }
 
@@ -243,8 +237,9 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
        * available printer in the class.
        */
 
-        fputs(_("INFO: Unable to contact printer, queuing on next "
-               "printer in class...\n"), stderr);
+        _cupsLangPrintFilter(stderr, "INFO",
+                            _("Unable to contact printer, queuing on next "
+                              "printer in class."));
 
        /*
         * Sleep 5 seconds to keep the job from requeuing too rapidly...
@@ -257,13 +252,13 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
 
       if (errno == EBUSY)
       {
-        fputs(_("INFO: Printer busy; will retry in 30 seconds...\n"), stderr);
+        _cupsLangPrintFilter(stderr, "INFO",
+                            _("Printer busy; will retry in 30 seconds."));
        sleep(30);
       }
       else
       {
-       fprintf(stderr, _("ERROR: Unable to open device file \"%s\": %s\n"),
-               resource, strerror(errno));
+       _cupsLangPrintError("ERROR", _("Unable to open device file"));
        return (CUPS_BACKEND_FAILED);
       }
     }
@@ -294,35 +289,36 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
       * Get the name...
       */
 
-      for (ptr = name; *options && *options != '=';)
-        if (ptr < (name + sizeof(name) - 1))
-          *ptr++ = *options++;
-      *ptr = '\0';
+      name = options;
+
+      while (*options && *options != '=' && *options != '+' && *options != '&')
+        options ++;
+
+      if ((sep = *options) != '\0')
+        *options++ = '\0';
 
-      if (*options == '=')
+      if (sep == '=')
       {
        /*
         * Get the value...
        */
 
-        options ++;
-
-       for (ptr = value; *options && *options != '+' && *options != '&';)
-          if (ptr < (value + sizeof(value) - 1))
-            *ptr++ = *options++;
-       *ptr = '\0';
+        value = options;
 
-       if (*options == '+' || *options == '&')
+       while (*options && *options != '+' && *options != '&')
          options ++;
+
+        if (*options)
+         *options++ = '\0';
       }
       else
-        value[0] = '\0';
+        value = (char *)"";
 
      /*
       * Process the option...
       */
 
-      if (!strcasecmp(name, "baud"))
+      if (!_cups_strcasecmp(name, "baud"))
       {
        /*
         * Set the baud rate...
@@ -379,13 +375,13 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
              break;
 #  endif /* B230400 */
           default :
-             fprintf(stderr, _("WARNING: Unsupported baud rate %s!\n"),
-                     value);
+             _cupsLangPrintFilter(stderr, "WARNING",
+                                  _("Unsupported baud rate: %s"), value);
              break;
        }
 #endif /* B19200 == 19200 */
       }
-      else if (!strcasecmp(name, "bits"))
+      else if (!_cups_strcasecmp(name, "bits"))
       {
        /*
         * Set number of data bits...
@@ -406,25 +402,25 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
              break;
        }
       }
-      else if (!strcasecmp(name, "parity"))
+      else if (!_cups_strcasecmp(name, "parity"))
       {
        /*
        * Set parity checking...
        */
 
-       if (!strcasecmp(value, "even"))
+       if (!_cups_strcasecmp(value, "even"))
        {
          opts.c_cflag |= PARENB;
           opts.c_cflag &= ~PARODD;
        }
-       else if (!strcasecmp(value, "odd"))
+       else if (!_cups_strcasecmp(value, "odd"))
        {
          opts.c_cflag |= PARENB;
           opts.c_cflag |= PARODD;
        }
-       else if (!strcasecmp(value, "none"))
+       else if (!_cups_strcasecmp(value, "none"))
          opts.c_cflag &= ~PARENB;
-       else if (!strcasecmp(value, "space"))
+       else if (!_cups_strcasecmp(value, "space"))
        {
         /*
          * Note: we only support space parity with 7 bits per character...
@@ -434,7 +430,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
           opts.c_cflag |= CS8;
          opts.c_cflag &= ~PARENB;
         }
-       else if (!strcasecmp(value, "mark"))
+       else if (!_cups_strcasecmp(value, "mark"))
        {
         /*
          * Note: we only support mark parity with 7 bits per character
@@ -447,29 +443,29 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
           opts.c_cflag |= CSTOPB;
         }
       }
-      else if (!strcasecmp(name, "flow"))
+      else if (!_cups_strcasecmp(name, "flow"))
       {
        /*
        * Set flow control...
        */
 
-       if (!strcasecmp(value, "none"))
+       if (!_cups_strcasecmp(value, "none"))
        {
          opts.c_iflag &= ~(IXON | IXOFF);
           opts.c_cflag &= ~CRTSCTS;
        }
-       else if (!strcasecmp(value, "soft"))
+       else if (!_cups_strcasecmp(value, "soft"))
        {
          opts.c_iflag |= IXON | IXOFF;
           opts.c_cflag &= ~CRTSCTS;
        }
-       else if (!strcasecmp(value, "hard") ||
-                !strcasecmp(value, "rtscts"))
+       else if (!_cups_strcasecmp(value, "hard") ||
+                !_cups_strcasecmp(value, "rtscts"))
         {
          opts.c_iflag &= ~(IXON | IXOFF);
           opts.c_cflag |= CRTSCTS;
        }
-       else if (!strcasecmp(value, "dtrdsr"))
+       else if (!_cups_strcasecmp(value, "dtrdsr"))
        {
          opts.c_iflag &= ~(IXON | IXOFF);
           opts.c_cflag &= ~CRTSCTS;
@@ -477,7 +473,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
          dtrdsr = 1;
        }
       }
-      else if (!strcasecmp(name, "stop"))
+      else if (!_cups_strcasecmp(name, "stop"))
       {
         switch (atoi(value))
        {
@@ -503,7 +499,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
   * stdin (otherwise you can't cancel raw jobs...)
   */
 
-  if (print_fd != 0)
+  if (!print_fd)
   {
 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
     sigset(SIGTERM, SIG_IGN);
@@ -560,7 +556,8 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
       if (!print_bytes)
        FD_SET(print_fd, &input);
       FD_SET(device_fd, &input);
-      FD_SET(CUPS_SC_FD, &input);
+      if (!print_bytes && !side_eof)
+        FD_SET(CUPS_SC_FD, &input);
 
       FD_ZERO(&output);
       if (print_bytes)
@@ -574,7 +571,16 @@ main(int  argc,                            /* I - Number of command-line arguments (6 or 7) */
       */
 
       if (FD_ISSET(CUPS_SC_FD, &input))
-        side_cb(print_fd, device_fd, 1);
+      {
+       /*
+       * Do the side-channel request, then start back over in the select
+       * loop since it may have read from print_fd...
+       */
+
+        if (side_cb(print_fd, device_fd, 1))
+         side_eof = 1;
+       continue;
+      }
 
      /*
       * Check if we have back-channel data ready...
@@ -585,7 +591,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
        if ((bc_bytes = read(device_fd, bc_buffer, sizeof(bc_buffer))) > 0)
        {
          fprintf(stderr,
-                 "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data!\n",
+                 "DEBUG: Received " CUPS_LLFMT " bytes of back-channel data\n",
                  CUPS_LLCAST bc_bytes);
           cupsBackChannelWrite(bc_buffer, bc_bytes, 1.0);
        }
@@ -605,7 +611,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
 
          if (errno != EAGAIN || errno != EINTR)
          {
-           perror("ERROR: Unable to read print data");
+           perror("DEBUG: Unable to read print data");
 
             tcsetattr(device_fd, TCSADRAIN, &origopts);
 
@@ -681,7 +687,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
 
          if (errno != EAGAIN && errno != EINTR && errno != ENOTTY)
          {
-           perror("ERROR: Unable to write print data");
+           perror("DEBUG: Unable to write print data");
 
             tcsetattr(device_fd, TCSADRAIN, &origopts);
 
@@ -716,7 +722,7 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
   if (print_fd != 0)
     close(print_fd);
 
-  return (total_bytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
+  return (CUPS_BACKEND_OK);
 }
 
 
@@ -727,16 +733,18 @@ main(int  argc,                           /* I - Number of command-line arguments (6 or 7) */
 static void
 list_devices(void)
 {
-#if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
   static char  *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
                                        /* Funky hex numbering used for some *
                                         * devices                           */
-#endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */
+#endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ || __FreeBSD_kernel__ */
+
 
 #ifdef __linux
   int                  i, j;           /* Looping vars */
   int                  fd;             /* File descriptor */
   char                 device[255];    /* Device filename */
+  char                 info[255];      /* Device info/description */
 #  ifdef TIOCGSERIAL
   struct serial_struct serinfo;        /* serial port info */
 #  endif /* TIOCGSERIAL */
@@ -771,32 +779,35 @@ list_devices(void)
 
       close(fd);
 
+      snprintf(info, sizeof(info),
+              _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
 #  if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
-      printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n",
-             device, i + 1);
+      printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device, info);
 #  else
-      printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
-             device, i + 1);
+      printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
 #  endif /* _ARCH_PPC || powerpc || __powerpc */
     }
   }
 
   for (i = 0; i < 16; i ++)
   {
+    snprintf(info, sizeof(info),
+            _cupsLangString(cupsLangDefault(), _("USB Serial Port #%d")),
+            i + 1);
+
     sprintf(device, "/dev/usb/ttyUSB%d", i);
     if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
     {
       close(fd);
-      printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
-             device, i + 1);
+      printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device, info);
     }
 
     sprintf(device, "/dev/ttyUSB%d", i);
     if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
     {
       close(fd);
-      printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
-             device, i + 1);
+      printf("serial serial:%s?baud=230400 \"Unknown\" \"%s\"\n", device, info);
     }
   }
 
@@ -808,9 +819,9 @@ list_devices(void)
       if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
       {
         close(fd);
+
         printf("serial serial:%s?baud=115200 \"Unknown\" "
-              "\"Equinox ESP %d Port #%d\"\n",
-               device, i, j + 1);
+              "\"Equinox ESP %d Port #%d\"\n", device, i, j + 1);
       }
     }
   }
@@ -913,8 +924,9 @@ list_devices(void)
        }
       }
 #elif defined(__sun)
-  int          i, j, n;        /* Looping vars */
-  char         device[255];    /* Device filename */
+  int          i, j, n;                /* Looping vars */
+  char         device[255];            /* Device filename */
+  char         info[255];              /* Device info/description */
 
 
  /*
@@ -924,14 +936,17 @@ list_devices(void)
   for (i = 0; i < 26; i ++)
   {
     sprintf(device, "/dev/cua/%c", 'a' + i);
-    if (access(device, 0) == 0)
+    if (!access(device, 0))
+    {
+      snprintf(info, sizeof(info),
+              _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
 #  ifdef B115200
-      printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
-             device, i + 1);
+      printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
 #  else
-      printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
-             device, i + 1);
+      printf("serial serial:%s?baud=38400 \"Unknown\" \"%s\"\n", device, info);
 #  endif /* B115200 */
+    }
   }
 
  /*
@@ -1027,10 +1042,11 @@ list_devices(void)
       printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
              device, i + 1);
   }
-#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-  int  i, j;           /* Looping vars */
-  int  fd;             /* File descriptor */
-  char device[255];    /* Device filename */
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
+  int  i, j;                           /* Looping vars */
+  int  fd;                             /* File descriptor */
+  char device[255];                    /* Device filename */
+  char info[255];                      /* Device info/description */
 
 
  /*
@@ -1043,8 +1059,11 @@ list_devices(void)
     if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
     {
       close(fd);
-      printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n",
-             device, i + 1);
+
+      snprintf(info, sizeof(info),
+              _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
+      printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
     }
   }
 
@@ -1118,9 +1137,10 @@ list_devices(void)
     }
   }
 #elif defined(__NetBSD__)
-  int  i, j;           /* Looping vars */
-  int  fd;             /* File descriptor */
-  char device[255];    /* Device filename */
+  int  i, j;                           /* Looping vars */
+  int  fd;                             /* File descriptor */
+  char device[255];                    /* Device filename */
+  char info[255];                      /* Device info/description */
 
 
  /*
@@ -1133,8 +1153,11 @@ list_devices(void)
     if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
     {
       close(fd);
-      printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
-             device, i + 1);
+
+      snprintf(info, sizeof(info),
+              _cupsLangString(cupsLangDefault(), _("Serial Port #%d")), i + 1);
+
+      printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", device, info);
     }
   }
 
@@ -1187,38 +1210,51 @@ list_devices(void)
       {
        CFTypeRef       serialNameAsCFString;
        CFTypeRef       bsdPathAsCFString;
+       CFTypeRef       hiddenVal;
        char            serialName[128];
        char            bsdPath[1024];
        Boolean         result;
 
 
-       serialNameAsCFString =
-           IORegistryEntryCreateCFProperty(serialService,
-                                           CFSTR(kIOTTYDeviceKey),
-                                           kCFAllocatorDefault, 0);
-       if (serialNameAsCFString)
+       /* Check if hidden... */
+       hiddenVal = IORegistryEntrySearchCFProperty(serialService,
+                                                   kIOServicePlane,
+                                                   CFSTR("HiddenPort"),
+                                                   kCFAllocatorDefault,
+                                                   kIORegistryIterateRecursively |
+                                                   kIORegistryIterateParents);
+       if (hiddenVal)
+         CFRelease(hiddenVal); /* This interface should not be used */
+       else
        {
-         result = CFStringGetCString(serialNameAsCFString, serialName,
-                                     sizeof(serialName),
-                                     kCFStringEncodingASCII);
-         CFRelease(serialNameAsCFString);
-
-         if (result)
+         serialNameAsCFString =
+             IORegistryEntryCreateCFProperty(serialService,
+                                             CFSTR(kIOTTYDeviceKey),
+                                             kCFAllocatorDefault, 0);
+         if (serialNameAsCFString)
          {
-           bsdPathAsCFString =
-               IORegistryEntryCreateCFProperty(serialService,
-                                               CFSTR(kIOCalloutDeviceKey),
-                                               kCFAllocatorDefault, 0);
-           if (bsdPathAsCFString)
+           result = CFStringGetCString(serialNameAsCFString, serialName,
+                                       sizeof(serialName),
+                                       kCFStringEncodingASCII);
+           CFRelease(serialNameAsCFString);
+
+           if (result)
            {
-             result = CFStringGetCString(bsdPathAsCFString, bsdPath,
-                                         sizeof(bsdPath),
-                                         kCFStringEncodingASCII);
-             CFRelease(bsdPathAsCFString);
-
-             if (result)
-               printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
-                      bsdPath, serialName);
+             bsdPathAsCFString =
+                 IORegistryEntryCreateCFProperty(serialService,
+                                                 CFSTR(kIOCalloutDeviceKey),
+                                                 kCFAllocatorDefault, 0);
+             if (bsdPathAsCFString)
+             {
+               result = CFStringGetCString(bsdPathAsCFString, bsdPath,
+                                           sizeof(bsdPath),
+                                           kCFStringEncodingASCII);
+               CFRelease(bsdPathAsCFString);
+
+               if (result)
+                 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n",
+                        bsdPath, serialName);
+             }
            }
          }
        }
@@ -1241,7 +1277,7 @@ list_devices(void)
  * 'side_cb()' - Handle side-channel requests...
  */
 
-static void
+static int                             /* O - 0 on success, -1 on error */
 side_cb(int print_fd,                  /* I - Print file */
         int device_fd,                 /* I - Device file */
        int use_bc)                     /* I - Using back-channel? */
@@ -1255,10 +1291,7 @@ side_cb(int print_fd,                    /* I - Print file */
   datalen = sizeof(data);
 
   if (cupsSideChannelRead(&command, &status, data, &datalen, 1.0))
-  {
-    fputs(_("WARNING: Failed to read side-channel request!\n"), stderr);
-    return;
-  }
+    return (-1);
 
   switch (command)
   {
@@ -1274,6 +1307,7 @@ side_cb(int print_fd,                     /* I - Print file */
         break;
 
     case CUPS_SC_CMD_GET_BIDI :
+       status  = CUPS_SC_STATUS_OK;
         data[0] = use_bc;
         datalen = 1;
         break;
@@ -1284,10 +1318,10 @@ side_cb(int print_fd,                   /* I - Print file */
        break;
   }
 
-  cupsSideChannelWrite(command, status, data, datalen, 1.0);
+  return (cupsSideChannelWrite(command, status, data, datalen, 1.0));
 }
 
 
 /*
- * End of "$Id: serial.c 6591 2007-06-21 20:35:28Z mike $".
+ * End of "$Id: serial.c 7647 2008-06-16 17:39:40Z mike $".
  */