]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/process.c
Import CUPS 1.4svn r7023 into easysw/current.
[thirdparty/cups.git] / scheduler / process.c
index cba826f50be29cc115cff8959472a8a7bcdfcaa2..56f748566124426ad33e85fe8848b961653abca9 100644 (file)
@@ -1,30 +1,23 @@
 /*
- * "$Id: process.c 4719 2005-09-28 21:12:44Z mike $"
+ * "$Id: process.c 6987 2007-09-25 15:43:44Z mike $"
  *
  *   Process management routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 1997-2005 by Easy Software Products, all rights reserved.
+ *   Copyright 2007 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
- *   "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
+ *   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/".
  *
  * Contents:
  *
- *   cupsdEndProcess()   - End a process.
- *   cupsdStartProcess() - Start a process.
+ *   cupsdEndProcess()    - End a process.
+ *   cupsdFinishProcess() - Finish a process and get its name.
+ *   cupsdStartProcess()  - Start a process.
+ *   compare_procs()      - Compare two processes.
  */
 
 /*
 
 #include "cupsd.h"
 #include <grp.h>
+#if defined(__APPLE__)
+#  include <libgen.h>
+#endif /* __APPLE__ */ 
+
+
+/*
+ * Process structure...
+ */
+
+typedef struct
+{
+  int  pid;                            /* Process ID */
+  char name[1];                        /* Name of process */
+} cupsd_proc_t;
+
+
+/*
+ * Local globals...
+ */
+
+static cups_array_t    *process_array = NULL;
+
+
+/*
+ * Local functions...
+ */
+
+static int     compare_procs(cupsd_proc_t *a, cupsd_proc_t *b);
 
 
 /*
@@ -50,6 +71,34 @@ cupsdEndProcess(int pid,             /* I - Process ID */
 }
 
 
+/*
+ * 'cupsdFinishProcess()' - Finish a process and get its name.
+ */
+
+const char *                           /* O - Process name */
+cupsdFinishProcess(int  pid,           /* I - Process ID */
+                   char *name,         /* I - Name buffer */
+                  int  namelen)        /* I - Size of name buffer */
+{
+  cupsd_proc_t key,                    /* Search key */
+               *proc;                  /* Matching process */
+
+
+  key.pid = pid;
+
+  if ((proc = (cupsd_proc_t *)cupsArrayFind(process_array, &key)) != NULL)
+  {
+    strlcpy(name, proc->name, namelen);
+    cupsArrayRemove(process_array, proc);
+    free(proc);
+
+    return (name);
+  }
+  else
+    return ("unknown");
+}
+
+
 /*
  * 'cupsdStartProcess()' - Start a process.
  */
@@ -63,18 +112,64 @@ cupsdStartProcess(
     int        outfd,                  /* I - Standard output file descriptor */
     int        errfd,                  /* I - Standard error file descriptor */
     int        backfd,                 /* I - Backchannel file descriptor */
+    int        sidefd,                 /* I - Sidechannel file descriptor */
     int        root,                   /* I - Run as root? */
     int        *pid)                   /* O - Process ID */
 {
+  cupsd_proc_t *proc;                  /* New process record */
 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
-  struct sigaction     action;         /* POSIX signal handler */
+  struct sigaction action;             /* POSIX signal handler */
 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+#if defined(__APPLE__)
+  char         processPath[1024],      /* CFProcessPath environment variable */
+               linkpath[1024];         /* Link path for symlinks... */
+  int          linkbytes;              /* Bytes for link path */
+#endif /* __APPLE__ */
 
 
   cupsdLogMessage(CUPSD_LOG_DEBUG2,
                   "cupsdStartProcess(\"%s\", %p, %p, %d, %d, %d)",
                   command, argv, envp, infd, outfd, errfd);
 
+  if (access(command, X_OK))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to execute %s: %s", command,
+                    strerror(errno));
+    *pid = 0;
+    return (0);
+  }
+
+#if defined(__APPLE__)
+  if (envp)
+  {
+   /*
+    * Add special voodoo magic for MacOS X - this allows MacOS X 
+    * programs to access their bundle resources properly...
+    */
+
+    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(processPath, sizeof(processPath), "CFProcessPath=%s",
+                linkpath);
+      else
+       snprintf(processPath, sizeof(processPath), "CFProcessPath=%s/%s",
+                dirname((char *)command), linkpath);
+    }
+    else
+      snprintf(processPath, sizeof(processPath), "CFProcessPath=%s", command);
+
+    envp[0] = processPath;             /* Replace <CFProcessPath> string */
+  }
+#endif /* __APPLE__ */
+
  /*
   * Block signals before forking...
   */
@@ -122,6 +217,12 @@ cupsdStartProcess(
         open("/dev/null", O_RDWR);
       fcntl(3, F_SETFL, O_NDELAY);
     }
+    if (sidefd != 4 && sidefd > 0)
+    {
+      close(4);
+      dup(sidefd);
+      fcntl(4, F_SETFL, O_NDELAY);
+    }
 
    /*
     * Change the priority of the process based on the FilterNice setting.
@@ -142,10 +243,10 @@ cupsdStartProcess(
       */
 
       if (setgid(Group))
-        exit(errno);
+       exit(errno);
 
       if (setgroups(1, &Group))
-        exit(errno);
+       exit(errno);
 
       if (setuid(User))
         exit(errno);
@@ -156,6 +257,7 @@ cupsdStartProcess(
       * Reset group membership to just the main one we belong to.
       */
 
+      setgid(Group);
       setgroups(1, &Group);
     }
 
@@ -212,6 +314,22 @@ cupsdStartProcess(
 
     *pid = 0;
   }
+  else
+  {
+    if (!process_array)
+      process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL);
+    if (process_array)
+    {
+      if ((proc = calloc(1, sizeof(cupsd_proc_t) + strlen(command))) != NULL)
+      {
+        proc->pid = *pid;
+       strcpy(proc->name, command);
+
+       cupsArrayAdd(process_array, proc);
+      }
+    }
+  }
 
   cupsdReleaseSignals();
 
@@ -220,5 +338,17 @@ cupsdStartProcess(
 
 
 /*
- * End of "$Id: process.c 4719 2005-09-28 21:12:44Z mike $".
+ * 'compare_procs()' - Compare two processes.
+ */
+
+static int                             /* O - Result of comparison */
+compare_procs(cupsd_proc_t *a,         /* I - First process */
+              cupsd_proc_t *b)         /* I - Second process */
+{
+  return (a->pid - b->pid);
+}
+
+
+/*
+ * End of "$Id: process.c 6987 2007-09-25 15:43:44Z mike $".
  */