www.gusucode.com > VC++版的邮件服务器源程序源码程序 > VC++版的邮件服务器源程序源码程序\code\MainLinux.cpp
//Download by http://www.NewXing.com /* * XMail by Davide Libenzi ( Intranet and Internet mail server ) * Copyright (C) 1999,..,2004 Davide Libenzi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Davide Libenzi <davidel@xmailserver.org> * */ #include "SysInclude.h" #include "SysDep.h" #include "SvrDefines.h" #include "SList.h" #include "ShBlocks.h" #include "UsrUtils.h" #include "SvrUtils.h" #include "MessQueue.h" #include "SMAILUtils.h" #include "QueueUtils.h" #include "AppDefines.h" #include "MailSvr.h" #define RUNNING_PIDS_DIR "/var/run" #define DEVNULL "/dev/null" #define NOFILE 64 #define XMAIL_DEBUG_OPTION "-Md" #define XMAIL_PIDDIR_ENV "XMAIL_PID_DIR" static int MnEventLog(char const *pszFormat, ...); static char const *MnGetPIDDir(void); static int MnSavePID(char const *pszPidFile); static int MnRemovePID(char const *pszPidFile); static void MnSetupStdHandles(void); static int MnDaemonBootStrap(void); static int MnIsDebugStartup(int iArgCount, char *pszArgs[]); static int MnDaemonStartup(int iArgCount, char *pszArgs[]); static int MnEventLog(char const *pszFormat, ...) { openlog(APP_NAME_STR, LOG_PID, LOG_DAEMON); va_list Args; va_start(Args, pszFormat); char szBuffer[2048] = ""; vsnprintf(szBuffer, sizeof(szBuffer) - 1, pszFormat, Args); syslog(LOG_ERR, "%s", szBuffer); va_end(Args); closelog(); return (0); } static char const *MnGetPIDDir(void) { char const *pszPIDDir = getenv(XMAIL_PIDDIR_ENV); return ((pszPIDDir != NULL) ? pszPIDDir: RUNNING_PIDS_DIR); } static int MnSavePID(char const *pszPidFile) { char szPidFile[SYS_MAX_PATH] = ""; snprintf(szPidFile, sizeof(szPidFile) - 1, "%s/%s.pid", MnGetPIDDir(), pszPidFile); FILE *pFile = fopen(szPidFile, "w"); if (pFile == NULL) { perror(szPidFile); return (-errno); } fprintf(pFile, "%u", (unsigned int) getpid()); fclose(pFile); return (0); } static int MnRemovePID(char const *pszPidFile) { char szPidFile[SYS_MAX_PATH] = ""; snprintf(szPidFile, sizeof(szPidFile) - 1, "%s/%s.pid", MnGetPIDDir(), pszPidFile); if (unlink(szPidFile) != 0) { perror(szPidFile); return (-errno); } return (0); } static void MnSetupStdHandles(void) { int iFD = open(DEVNULL, O_RDWR, 0); if (iFD == -1) { MnEventLog("Cannot open file %s : %s", DEVNULL, strerror(errno)); exit(errno); } if ((dup2(iFD, 0) == -1) || (dup2(iFD, 1) == -1) || (dup2(iFD, 2) == -1)) { MnEventLog("File descriptor duplication error : %s", strerror(errno)); exit(errno); } close(iFD); } static int MnDaemonBootStrap(void) { /////////////////////////////////////////////////////////////////////////////// // This code is inspired from the code of the great Richard Stevens books. // May You RIP in programmers paradise great Richard. // I suggest You to buy all his collection, soon ! /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // For BSD /////////////////////////////////////////////////////////////////////////////// #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif /////////////////////////////////////////////////////////////////////////////// // 1st fork /////////////////////////////////////////////////////////////////////////////// int iChildPID = fork(); if (iChildPID < 0) { MnEventLog("Cannot fork : %s", strerror(errno)); exit(errno); } else if (iChildPID > 0) exit(0); /////////////////////////////////////////////////////////////////////////////// // Disassociate from controlling terminal and process group. Ensure the process // can't reacquire a new controlling terminal. /////////////////////////////////////////////////////////////////////////////// if (setpgrp() == -1) { MnEventLog("Can't change process group : %s", strerror(errno)); exit(errno); } signal(SIGHUP, SIG_IGN); /////////////////////////////////////////////////////////////////////////////// // 2nd fork /////////////////////////////////////////////////////////////////////////////// iChildPID = fork(); if (iChildPID < 0) { MnEventLog("Cannot fork : %s", strerror(errno)); exit(errno); } else if (iChildPID > 0) exit(0); /////////////////////////////////////////////////////////////////////////////// // Close open file descriptors /////////////////////////////////////////////////////////////////////////////// for (int fd = 0; fd < NOFILE; fd++) close(fd); /////////////////////////////////////////////////////////////////////////////// // Set std handles /////////////////////////////////////////////////////////////////////////////// MnSetupStdHandles(); /////////////////////////////////////////////////////////////////////////////// // Probably got set to EBADF from a close /////////////////////////////////////////////////////////////////////////////// errno = 0; /////////////////////////////////////////////////////////////////////////////// // Move the current directory to root, to make sure we aren't on a mounted // filesystem. /////////////////////////////////////////////////////////////////////////////// chdir("/"); /////////////////////////////////////////////////////////////////////////////// // Clear any inherited file mode creation mask. /////////////////////////////////////////////////////////////////////////////// umask(0); /////////////////////////////////////////////////////////////////////////////// // Ignore childs dead. /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // System V /////////////////////////////////////////////////////////////////////////////// signal(SIGCLD, SIG_IGN); return (0); } static int MnIsDebugStartup(int iArgCount, char *pszArgs[]) { for (int ii = 0; ii < iArgCount; ii++) if (strcmp(pszArgs[ii], XMAIL_DEBUG_OPTION) == 0) return (1); return (0); } static int MnDaemonStartup(int iArgCount, char *pszArgs[]) { /////////////////////////////////////////////////////////////////////////////// // Daemon bootstrap code if We're not in debug mode /////////////////////////////////////////////////////////////////////////////// if (!MnIsDebugStartup(iArgCount, pszArgs)) MnDaemonBootStrap(); /////////////////////////////////////////////////////////////////////////////// // Extract PID file name /////////////////////////////////////////////////////////////////////////////// char const *pszPidFile = strrchr(pszArgs[0], '/'); pszPidFile = (pszPidFile != NULL) ? (pszPidFile + 1): pszArgs[0]; /////////////////////////////////////////////////////////////////////////////// // Create PID file /////////////////////////////////////////////////////////////////////////////// MnSavePID(pszPidFile); int iServerResult = SvrMain(iArgCount, pszArgs); /////////////////////////////////////////////////////////////////////////////// // Remove PID file /////////////////////////////////////////////////////////////////////////////// MnRemovePID(pszPidFile); return (iServerResult); } int main(int iArgCount, char *pszArgs[]) { return (MnDaemonStartup(iArgCount, pszArgs)); }