+++ /dev/null
-/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
- * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
- * specific language governing rights and limitations under the License.
- */
-
-
-//
-// demon - support code for writing UNIXoid demons
-//
-#include <Security/daemon.h>
-#include <Security/logging.h>
-#include <Security/debugging.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-namespace Security {
-namespace Daemon {
-
-
-//
-// Daemonize this process, the UNIX way.
-//
-bool incarnate()
-{
- // fork with slight resilience
- for (int forkTries = 1; forkTries <= 5; forkTries++) {
- switch (fork()) {
- case 0: // child
- // we are the daemon process (Har! Har!)
- break;
- case -1: // parent: fork failed
- switch (errno) {
- case EAGAIN:
- case ENOMEM:
- Syslog::warning("fork() short on resources (errno=%d); retrying", errno);
- sleep(forkTries);
- continue;
- default:
- Syslog::error("fork() failed (errno=%d)", errno);
- return false;
- }
- default: // parent
- // @@@ we could close an assurance loop here, but we don't (yet?)
- exit(0);
- }
- }
-
- // fork succeeded; we are the child; parent is terminating
-
- // create new session (the magic set-me-apart system call)
- setsid();
-
- // redirect standard channels to /dev/null
- close(0); // fail silently in case 0 is closed
- if (open("/dev/null", O_RDWR, 0) == 0) { // /dev/null could be missing, I suppose...
- dup2(0, 1);
- dup2(0, 2);
- }
-
- // ready to roll
- return true;
-}
-
-
-//
-// Re-execute myself.
-// This is a pretty bad hack for libraries that are pretty broken and (essentially)
-// don't work after a fork() unless you also exec().
-//
-// WARNING: Don't even THINK of doing this in a setuid-anything program.
-//
-bool executeSelf(char **argv)
-{
- static const char reExecEnv[] = "_RE_EXECUTE";
- if (getenv(reExecEnv)) { // was re-executed
- secdebug("daemon", "self-execution complete");
- unsetenv(reExecEnv);
- return true;
- } else {
- setenv(reExecEnv, "go", 1);
- secdebug("daemon", "self-executing (ouch!)");
- execv(argv[0], argv);
- perror("re-execution");
- Syslog::error("Re-execution attempt failed");
- return false;
- }
-}
-
-
-} // end namespace Daemon
-} // end namespace Security