]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/util.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / scheduler / util.c
index 2771f12a8ebe0ce387bbf8a145d9e5a3236a5407..5e67d8028122a1fc6c442be8f342b9bd3e3e3e29 100644 (file)
@@ -1,34 +1,14 @@
 /*
- * "$Id: util.c 177 2006-06-21 00:20:03Z jlovell $"
+ * Mini-daemon utility functions for CUPS.
  *
- *   Mini-daemon utility functions for the Common UNIX Printing System (CUPS).
+ * Copyright 2007-2014 by Apple Inc.
+ * Copyright 1997-2005 by Easy Software Products.
  *
- *   Copyright 1997-2005 by Easy Software Products.
- *
- *   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:
- *
- *   cupsdCompareNames()   - Compare two names.
- *   cupsdSendIPPGroup()   - Send a group tag.
- *   cupsdSendIPPHeader()  - Send the IPP response header.
- *   cupsdSendIPPInteger() - Send an integer attribute.
- *   cupsdSendIPPString()  - Send a string attribute.
- *   cupsdSendIPPTrailer() - Send the end-of-message tag.
+ * 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"
+ * which should have been included with this file.  If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
  */
 
 /*
  */
 
 #include "util.h"
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef __APPLE__
+#  include <libgen.h>
+extern char **environ;
+#endif /* __APPLE__ */
 
 
 /*
  * 'cupsdCompareNames()' - Compare two names.
  *
- * This function basically does a strcasecmp() of the two strings,
+ * This function basically does a _cups_strcasecmp() of the two strings,
  * but is also aware of numbers so that "a2" < "a100".
  */
 
@@ -90,7 +77,7 @@ cupsdCompareNames(const char *s,      /* I - First string */
       else if (!isdigit(*s & 255) && isdigit(*t & 255))
         return (-1);
       else if (!isdigit(*s & 255) || !isdigit(*t & 255))
-        continue;     
+        continue;
 
       if (*s < *t)
         diff = -1;
@@ -152,6 +139,192 @@ cupsdCompareNames(const char *s,  /* I - First string */
 }
 
 
+/*
+ * 'cupsdCreateStringsArray()' - Create a CUPS array of strings.
+ */
+
+cups_array_t *                         /* O - CUPS array */
+cupsdCreateStringsArray(const char *s) /* I - Comma-delimited strings */
+{
+  if (!s || !*s)
+    return (NULL);
+  else
+    return (_cupsArrayNewStrings(s, ','));
+}
+
+
+/*
+ * 'cupsdExec()' - Run a program with the correct environment.
+ *
+ * On OS X, we need to update the CFProcessPath environment variable that
+ * is passed in the environment so the child can access its bundled resources.
+ */
+
+int                                    /* O - exec() status */
+cupsdExec(const char *command,         /* I - Full path to program */
+          char       **argv)           /* I - Command-line arguments */
+{
+#ifdef __APPLE__
+  int  i, j;                           /* Looping vars */
+  char *envp[500],                     /* Array of environment variables */
+       cfprocesspath[1024],            /* CFProcessPath environment variable */
+       linkpath[1024];                 /* Link path for symlinks... */
+  int  linkbytes;                      /* Bytes for link path */
+
+
+ /*
+  * Some OS X programs are bundled and need the CFProcessPath environment
+  * variable defined.  If the command is a symlink, resolve the link and point
+  * to the resolved location, otherwise, use the command path itself.
+  */
+
+  if ((linkbytes = readlink(command, linkpath, sizeof(linkpath) - 1)) > 0)
+  {
+   /*
+    * Yes, this is a symlink to the actual program, nul-terminate and
+    * use it...
+    */
+
+    linkpath[linkbytes] = '\0';
+
+    if (linkpath[0] == '/')
+      snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s",
+              linkpath);
+    else
+      snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s/%s",
+              dirname((char *)command), linkpath);
+  }
+  else
+    snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s", command);
+
+  envp[0] = cfprocesspath;
+
+ /*
+  * Copy the rest of the environment except for any CFProcessPath that may
+  * already be there...
+  */
+
+  for (i = 1, j = 0;
+       environ[j] && i < (int)(sizeof(envp) / sizeof(envp[0]) - 1);
+       j ++)
+    if (strncmp(environ[j], "CFProcessPath=", 14))
+      envp[i ++] = environ[j];
+
+  envp[i] = NULL;
+
+ /*
+  * Use execve() to run the program...
+  */
+
+  return (execve(command, argv, envp));
+
+#else
+ /*
+  * On other operating systems, just call execv() to use the same environment
+  * variables as the parent...
+  */
+
+  return (execv(command, argv));
+#endif /* __APPLE__ */
+}
+
+
+/*
+ * 'cupsdPipeCommand()' - Read output from a command.
+ */
+
+cups_file_t *                          /* O - CUPS file or NULL on error */
+cupsdPipeCommand(int        *pid,      /* O - Process ID or 0 on error */
+                 const char *command,  /* I - Command to run */
+                 char       **argv,    /* I - Arguments to pass to command */
+                uid_t      user)       /* I - User to run as or 0 for current */
+{
+  int  fd,                             /* Temporary file descriptor */
+       fds[2];                         /* Pipe file descriptors */
+
+
+ /*
+  * First create the pipe...
+  */
+
+  if (pipe(fds))
+  {
+    *pid = 0;
+    return (NULL);
+  }
+
+ /*
+  * Set the "close on exec" flag on each end of the pipe...
+  */
+
+  if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
+  {
+    close(fds[0]);
+    close(fds[1]);
+
+    *pid = 0;
+
+    return (NULL);
+  }
+
+  if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
+  {
+    close(fds[0]);
+    close(fds[1]);
+
+    *pid = 0;
+
+    return (NULL);
+  }
+
+ /*
+  * Then run the command...
+  */
+
+  if ((*pid = fork()) < 0)
+  {
+   /*
+    * Unable to fork!
+    */
+
+    *pid = 0;
+    close(fds[0]);
+    close(fds[1]);
+
+    return (NULL);
+  }
+  else if (!*pid)
+  {
+   /*
+    * Child comes here...
+    */
+
+    if (!getuid() && user)
+      setuid(user);                    /* Run as restricted user */
+
+    if ((fd = open("/dev/null", O_RDONLY)) > 0)
+    {
+      dup2(fd, 0);                     /* </dev/null */
+      close(fd);
+    }
+
+    dup2(fds[1], 1);                   /* >pipe */
+    close(fds[1]);
+
+    cupsdExec(command, argv);
+    exit(errno);
+  }
+
+ /*
+  * Parent comes here, open the input side of the pipe...
+  */
+
+  close(fds[1]);
+
+  return (cupsFileOpenFd(fds[0], "r"));
+}
+
+
 /*
  * 'cupsdSendIPPGroup()' - Send a group tag.
  */
@@ -179,6 +352,8 @@ cupsdSendIPPHeader(
  /*
   * Send IPP/1.1 response header: version number (2 bytes), status code
   * (2 bytes), and request ID (4 bytes)...
+  *
+  * TODO: Add version number (IPP/2.x and IPP/1.0) support.
   */
 
   putchar(1);
@@ -194,7 +369,6 @@ cupsdSendIPPHeader(
 }
 
 
-#if 0 /* Not currently used */
 /*
  * 'cupsdSendIPPInteger()' - Send an integer attribute.
  */
@@ -210,23 +384,25 @@ cupsdSendIPPInteger(
 
  /*
   * Send IPP integer value: value tag (1 byte), name length (2 bytes),
-  * name string (without nul), and value (4 bytes)...
+  * name string (without nul), value length (2 bytes), and value (4 bytes)...
   */
 
   putchar(value_tag);
 
   len = strlen(name);
-  putchar(len >> 8);
-  putchar(len);
+  putchar((int)(len >> 8));
+  putchar((int)len);
 
   fputs(name, stdout);
 
+  putchar(0);
+  putchar(4);
+
   putchar(value >> 24);
   putchar(value >> 16);
   putchar(value >> 8);
   putchar(value);
 }
-#endif /* 0 */
 
 
 /*
@@ -251,14 +427,14 @@ cupsdSendIPPString(
   putchar(value_tag);
 
   len = strlen(name);
-  putchar(len >> 8);
-  putchar(len);
+  putchar((int)(len >> 8));
+  putchar((int)len);
 
   fputs(name, stdout);
 
   len = strlen(value);
-  putchar(len >> 8);
-  putchar(len);
+  putchar((int)(len >> 8));
+  putchar((int)len);
 
   fputs(value, stdout);
 }
@@ -274,8 +450,3 @@ cupsdSendIPPTrailer(void)
   putchar(IPP_TAG_END);
   fflush(stdout);
 }
-
-
-/*
- * End of "$Id: util.c 177 2006-06-21 00:20:03Z jlovell $".
- */