1/* detach.c 2 Detach from the controlling terminal. 3 4 Copyright (C) 1992, 1993, 1995 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#include "uudefs.h" 28#include "system.h" 29#include "sysdep.h" 30 31#include <errno.h> 32 33#if HAVE_SYS_IOCTL_H 34#include <sys/ioctl.h> 35#endif 36 37#ifdef TIOCNOTTY 38#define HAVE_TIOCNOTTY 1 39#else 40#define HAVE_TIOCNOTTY 0 41#endif 42 43#if HAVE_FCNTL_H 44#include <fcntl.h> 45#else 46#if HAVE_SYS_FILE_H 47#include <sys/file.h> 48#endif 49#endif 50 51#ifndef O_RDONLY 52#define O_RDONLY 0 53#define O_WRONLY 1 54#define O_RDWR 2 55#endif 56 57#if HAVE_BROKEN_SETSID 58#undef HAVE_SETSID 59#define HAVE_SETSID 0 60#endif 61 62/* Detach from the controlling terminal. This is called by uucico if 63 it is calling out to another system, so that it can receive SIGHUP 64 signals from the port it calls out on. It is also called by uucico 65 just before it starts uuxqt, so that uuxqt is completely 66 independent of the terminal. */ 67 68void 69usysdep_detach () 70{ 71 pid_t igrp; 72 73 /* Make sure that we can open the log file. We do this now so that, 74 if we can't, a message will be written to stderr. After we leave 75 this routine, stderr will be closed. */ 76 ulog (LOG_NORMAL, (const char *) NULL); 77 78 /* Make sure we are not a process group leader. */ 79#if HAVE_BSD_PGRP 80 igrp = getpgrp (0); 81#else 82 igrp = getpgrp (); 83#endif 84 85 if (igrp == getpid ()) 86 { 87 boolean fignored; 88 pid_t ipid; 89 90 /* Ignore SIGHUP, since our process group leader is about to 91 die. */ 92 usset_signal (SIGHUP, SIG_IGN, FALSE, &fignored); 93 94 ipid = ixsfork (); 95 if (ipid < 0) 96 ulog (LOG_FATAL, "fork: %s", strerror (errno)); 97 98 if (ipid != 0) 99 _exit (EXIT_SUCCESS); 100 101 /* We'll always wind up as a child of process number 1, right? 102 Right? We have to wait for our parent to die before 103 reenabling SIGHUP. */ 104 while (getppid () != 1) 105 sleep (1); 106 107 ipid = getpid (); 108 ulog_id (ipid); 109 110 /* Restore SIGHUP catcher if it wasn't being ignored. */ 111 if (! fignored) 112 usset_signal (SIGHUP, ussignal, TRUE, (boolean *) NULL); 113 114 DEBUG_MESSAGE2 (DEBUG_PORT, 115 "usysdep_detach: Forked; old PID %ld, new pid %ld", 116 (long) igrp, (long) ipid); 117 } 118 119#if ! HAVE_SETSID && HAVE_TIOCNOTTY 120 /* Lose the original controlling terminal as well as our process 121 group. */ 122 { 123 int o; 124 125 o = open ((char *) "/dev/tty", O_RDONLY); 126 if (o >= 0) 127 { 128 (void) ioctl (o, TIOCNOTTY, (char *) NULL); 129 (void) close (o); 130 } 131 } 132#endif /* ! HAVE_SETSID && HAVE_TIOCNOTTY */ 133 134 /* Close stdin, stdout and stderr and reopen them on /dev/null, to 135 make sure we have no connection at all to the terminal. */ 136 (void) close (0); 137 (void) close (1); 138 (void) close (2); 139 if (open ((char *) "/dev/null", O_RDONLY) != 0 140 || open ((char *) "/dev/null", O_WRONLY) != 1 141 || open ((char *) "/dev/null", O_WRONLY) != 2) 142 ulog (LOG_FATAL, "open (/dev/null): %s", strerror (errno)); 143 144#if HAVE_SETSID 145 146 /* Under POSIX the setsid call creates a new session for which we 147 are the process group leader. It also detaches us from our 148 controlling terminal. */ 149 if (setsid () < 0) 150 ulog (LOG_ERROR, "setsid: %s", strerror (errno)); 151 152#else /* ! HAVE_SETSID */ 153 154#if ! HAVE_SETPGRP 155 #error Cannot detach from controlling terminal 156#endif 157 158 /* If we don't have setsid, we must use setpgrp. On an old System V 159 system setpgrp will make us the leader of a new process group and 160 detach the controlling terminal. On an old BSD system the call 161 setpgrp (0, 0) will set our process group to 0 so that we can 162 acquire a new controlling terminal (TIOCNOTTY may or may not have 163 already done that anyhow). */ 164#if HAVE_BSD_PGRP 165 if (setpgrp (0, 0) < 0) 166#else 167 if (setpgrp () < 0) 168#endif 169 { 170 /* Some systems seem to give EPERM errors inappropriately. */ 171 if (errno != EPERM) 172 ulog (LOG_ERROR, "setpgrp: %s", strerror (errno)); 173 } 174 175#endif /* ! HAVE_SETSID */ 176 177 /* At this point we have completely detached from our controlling 178 terminal. The next terminal device we open will probably become 179 our controlling terminal. */ 180} 181