Description: CUPS Upstart socket activation:
 Important to note:
 - Run by default in foreground (-f), not Foreground (-F). With -F CUPS
 closes all inherited file descriptors, which is not needed under
 upstart since it does that on our behalf, furthermore closing passed
 socket activation descriptors prevents us from using socket
 activation.
 - Force foreground (-f) mode if environment suggests that we are Upstart
 socket activated (similar to "-l" flag for launchd).
 - Initialize addrlen to sizeof(addr) to make getsockname() work.
 - Correct environment variable name used to check event type
 - Get UPSTART_FDS simply with atoi()
 - Perform explicit return code checking from getsockname function call
Author: Till Kamppeter <till.kamppeter@gmail.com>,
 Dimitri John Ledkov <xnox@ubuntu.com>
Bug: https://bugs.launchpad.net/ubuntu/+source/cups/+bug/1276713
--- a/scheduler/main.c
+++ b/scheduler/main.c
@@ -26,6 +26,8 @@
  *   launchd_checkin()     - Check-in with launchd and collect the listening
  *                           fds.
  *   launchd_checkout()    - Update the launchd KeepAlive file as needed.
+ *   upstart_checkin()     - Check-in with Upstart and collect the
+ *                           listening fds.
  *   parent_handler()      - Catch USR1/CHLD signals...
  *   process_children()    - Process all dead children...
  *   select_timeout()      - Calculate the select timeout value.
@@ -83,6 +85,7 @@
 static void		launchd_checkin(void);
 static void		launchd_checkout(void);
 #endif /* HAVE_LAUNCHD */
+static void		upstart_checkin(void);
 static void		parent_handler(int sig);
 static void		process_children(void);
 static void		sigchld_handler(int sig);
@@ -320,6 +323,14 @@
       usage(1);
     }
 
+  /* force non-disconnecting foreground mode upon upstart socket
+   * activation, as otherwise all fd's are closed before we get to use
+   * them */
+  if (getenv("UPSTART_FDS"))
+  {
+    fg      = 1;
+  }
+
   if (!ConfigurationFile)
     cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf");
 
@@ -573,6 +584,11 @@
 #endif /* HAVE_LAUNCHD */
 
  /*
+  * If we were started by Upstart get the listen sockets file descriptors...
+  */
+  upstart_checkin();
+
+ /*
   * Startup the server...
   */
 
@@ -761,6 +777,13 @@
 #endif /* HAVE_LAUNCHD */
 
        /*
+        * If we were started by Upstart get the listen sockets file
+	* descriptors...
+        */
+
+        upstart_checkin();
+
+       /*
         * Startup the server...
         */
 
@@ -1509,6 +1532,93 @@
 }
 #endif /* HAVE_LAUNCHD */
 
+static void
+upstart_checkin(void)
+{
+  /*
+   * Example socket event environment:
+   *
+   * UPSTART_INSTANCE=
+   * PORT=34568
+   * PROTO=inet
+   * UPSTART_JOB=foo5
+   * UPSTART_FDS=43
+   * UPSTART_EVENTS=socket
+   * ADDR=127.0.0.1
+   *
+   */
+  int fd = 0;
+  const char *e;
+  http_addr_t addr;
+  socklen_t addrlen = sizeof(addr);
+  cupsd_listener_t *lis;
+  char s[256];
+
+  if (!(e = getenv("UPSTART_EVENTS")))
+    return;
+
+  if (strcasecmp(e, "socket"))
+    return;
+
+  if (!(e = getenv("UPSTART_FDS")))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+		    "upstart_checkin: We got started via Upstart socket event but no environment variable UPSTART_FDS is not set");
+    return;
+  }
+
+  fd = atoi(e);
+
+  if (getsockname(fd, (struct sockaddr*) &addr, &addrlen) < 0)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+		    "upstart_checkin: Unable to get local address - %s",
+		    strerror(errno));
+    return;
+  }
+
+ /*
+  * Try to match the systemd socket address to one of the listeners...
+  */
+
+  for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
+       lis;
+       lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
+    if (httpAddrEqual(&lis->address, &addr))
+      break;
+
+  if (lis)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+		    "upstart_checkin: Matched existing listener %s with fd %d...",
+		    httpAddrString(&(lis->address), s, sizeof(s)), fd);
+  }
+  else
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+		    "upstart_checkin: Adding new listener %s with fd %d...",
+		    httpAddrString(&addr, s, sizeof(s)), fd);
+
+    if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL)
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+		      "upstart_checkin: Unable to allocate listener - "
+		      "%s.", strerror(errno));
+      exit(EXIT_FAILURE);
+    }
+
+    cupsArrayAdd(Listeners, lis);
+
+    memcpy(&lis->address, &addr, sizeof(lis->address));
+  }
+
+  lis->fd = fd;
+
+#  ifdef HAVE_SSL
+  if (_httpAddrPort(&(lis->address)) == 443)
+    lis->encryption = HTTP_ENCRYPT_ALWAYS;
+#  endif /* HAVE_SSL */
+}
 
 /*
  * 'parent_handler()' - Catch USR1/CHLD signals...
