00001 /* bg.c: handles moving the process to the background and forking, while 00002 * keeping threads happy. 00003 * 00004 * Copyright (C) 1997 Robey Pointer 00005 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Eggheads Development Team 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU General Public License 00009 * as published by the Free Software Foundation; either version 2 00010 * of the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00020 */ 00021 00022 #ifndef lint 00023 static const char rcsid[] = "$Id: bg.c,v 1.22 2004-10-17 05:14:07 stdarg Exp $"; 00024 #endif 00025 00026 #include <eggdrop/eggdrop.h> 00027 00028 #ifdef CYGWIN_HACKS 00029 # include <windows.h> 00030 #endif 00031 00032 #include <unistd.h> /* fork(), setpgid() */ 00033 #include <sys/wait.h> /* waitpid() */ 00034 #include <signal.h> /* kill() */ 00035 #include "main.h" /* fatal()*/ 00036 #include "bg.h" 00037 00038 /* When threads are started during eggdrop's init phase, we can't simply 00039 * fork() later on, because that only copies the VM space over and 00040 * doesn't actually duplicate the threads. 00041 * 00042 * To work around this, we fork() very early and let the parent process 00043 * wait in an event loop. As soon as the init phase is completed and we 00044 * would normally move to the background, the child process simply 00045 * signals its parent that it may now quit. This allows us to control 00046 * the terminal long enough to, e.g. properly feed error messages to 00047 * cron scripts and let the user abort the loading process by hitting 00048 * CTRL+C. 00049 * 00050 */ 00051 00052 /* The child has to keep the parent's pid so it can send it a signal when it's 00053 * time to exit. */ 00054 static int pipefd[2]; 00055 00056 void bg_begin_split() 00057 { 00058 int parent_pid = -1, child_pid = -1; 00059 int result; 00060 char temp = 0; 00061 00062 parent_pid = getpid(); 00063 00064 pipe(pipefd); 00065 00066 child_pid = fork(); 00067 if (child_pid == -1) fatal("CANNOT FORK PROCESS."); 00068 00069 /* Are we the child? */ 00070 if (child_pid == 0) { 00071 /* Yes. Continue as normal. */ 00072 return; 00073 } 00074 /* We are the parent. Just hang around until the child is done. When 00075 * the child wants us to exit, it will send us the signal and trigger 00076 * wait_for_child. */ 00077 close(pipefd[1]); 00078 result = read(pipefd[0], &temp, 1); 00079 00080 if (result <= 0) { 00081 printf("Eggdrop exited abnormally!\n"); 00082 exit(1); 00083 } 00084 else { 00085 printf("Eggdrop launched successfully into the background, pid = %d.\n", child_pid); 00086 exit(0); 00087 } 00088 } 00089 00090 void bg_finish_split() 00091 { 00092 char temp = 0; 00093 write(pipefd[1], &temp, 1); 00094 close(pipefd[1]); 00095 close(pipefd[0]); 00096 00097 #if HAVE_SETPGID && !defined(CYGWIN_HACKS) 00098 setpgid(0, 0); 00099 #endif 00100 freopen("/dev/null", "r", stdin); 00101 freopen("/dev/null", "w", stdout); 00102 freopen("/dev/null", "w", stderr); 00103 00104 #ifdef CYGWIN_HACKS 00105 FreeConsole(); 00106 #endif 00107 }