1/* 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// demon - support code for writing UNIXoid demons 27// 28#include <security_utilities/daemon.h> 29#include <security_utilities/logging.h> 30#include <security_utilities/debugging.h> 31#include <sys/types.h> 32#include <errno.h> 33#include <unistd.h> 34#include <fcntl.h> 35 36namespace Security { 37namespace Daemon { 38 39 40// 41// Daemonize this process, the UNIX way. 42// 43bool incarnate(bool doFork /*=true*/) 44{ 45 if (doFork) { 46 // fork with slight resilience 47 for (int forkTries = 1; forkTries <= 5; forkTries++) { 48 switch (fork()) { 49 case 0: // child 50 // we are the daemon process (Har! Har!) 51 break; 52 case -1: // parent: fork failed 53 switch (errno) { 54 case EAGAIN: 55 case ENOMEM: 56 Syslog::warning("fork() short on resources (errno=%d); retrying", errno); 57 sleep(forkTries); 58 continue; 59 default: 60 Syslog::error("fork() failed (errno=%d)", errno); 61 return false; 62 } 63 default: // parent 64 // @@@ we could close an assurance loop here, but we don't (yet?) 65 exit(0); 66 } 67 } 68 // fork succeeded; we are the child; parent is terminating 69 } 70 71 // create new session (the magic set-me-apart system call) 72 setsid(); 73 74 // redirect standard channels to /dev/null 75 close(0); // fail silently in case 0 is closed 76 if (open("/dev/null", O_RDWR, 0) == 0) { // /dev/null could be missing, I suppose... 77 dup2(0, 1); 78 dup2(0, 2); 79 } 80 81 // ready to roll 82 return true; 83} 84 85 86// 87// Re-execute myself. 88// This is a pretty bad hack for libraries that are pretty broken and (essentially) 89// don't work after a fork() unless you also exec(). 90// 91// WARNING: Don't even THINK of doing this in a setuid-anything program. 92// 93bool executeSelf(char **argv) 94{ 95 static const char reExecEnv[] = "_RE_EXECUTE"; 96 if (getenv(reExecEnv)) { // was re-executed 97 secdebug("daemon", "self-execution complete"); 98 unsetenv(reExecEnv); 99 return true; 100 } else { 101 setenv(reExecEnv, "go", 1); 102 secdebug("daemon", "self-executing (ouch!)"); 103 execv(argv[0], argv); 104 perror("re-execution"); 105 Syslog::error("Re-execution attempt failed"); 106 return false; 107 } 108} 109 110 111} // end namespace Daemon 112} // end namespace Security 113