MainBSD.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:8k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "SList.h"
  26. #include "ShBlocks.h"
  27. #include "UsrUtils.h"
  28. #include "SvrUtils.h"
  29. #include "MessQueue.h"
  30. #include "SMAILUtils.h"
  31. #include "QueueUtils.h"
  32. #include "AppDefines.h"
  33. #include "MailSvr.h"
  34. #define RUNNING_PIDS_DIR            "/var/run"
  35. #define DEVNULL                     "/dev/null"
  36. #if !defined(NOFILE)
  37. #define NOFILE                      64
  38. #endif // #if !defined(NOFILE)
  39. #define XMAIL_DEBUG_OPTION          "-Md"
  40. #define XMAIL_PIDDIR_ENV            "XMAIL_PID_DIR"
  41. static int MnEventLog(char const *pszFormat, ...);
  42. static char const *MnGetPIDDir(void);
  43. static int MnSavePID(char const *pszPidFile);
  44. static int MnRemovePID(char const *pszPidFile);
  45. static void MnSIGCLD(int iSignal);
  46. static void MnSetupStdHandles(void);
  47. static int MnDaemonBootStrap(void);
  48. static int MnIsDebugStartup(int iArgCount, char *pszArgs[]);
  49. static int MnDaemonStartup(int iArgCount, char *pszArgs[]);
  50. static int MnEventLog(char const *pszFormat, ...)
  51. {
  52. openlog(APP_NAME_STR, LOG_PID, LOG_DAEMON);
  53. va_list Args;
  54. va_start(Args, pszFormat);
  55. char szBuffer[2048] = "";
  56. vsnprintf(szBuffer, sizeof(szBuffer) - 1, pszFormat, Args);
  57. syslog(LOG_ERR, "%s", szBuffer);
  58. va_end(Args);
  59. closelog();
  60. return (0);
  61. }
  62. static char const *MnGetPIDDir(void)
  63. {
  64. char const *pszPIDDir = getenv(XMAIL_PIDDIR_ENV);
  65. return ((pszPIDDir != NULL) ? pszPIDDir: RUNNING_PIDS_DIR);
  66. }
  67. static int MnSavePID(char const *pszPidFile)
  68. {
  69. char szPidFile[SYS_MAX_PATH] = "";
  70. snprintf(szPidFile, sizeof(szPidFile) - 1, "%s/%s.pid", MnGetPIDDir(), pszPidFile);
  71. FILE *pFile = fopen(szPidFile, "w");
  72. if (pFile == NULL) {
  73. perror(szPidFile);
  74. return (-errno);
  75. }
  76. fprintf(pFile, "%u", (unsigned int) getpid());
  77. fclose(pFile);
  78. return (0);
  79. }
  80. static int MnRemovePID(char const *pszPidFile)
  81. {
  82. char szPidFile[SYS_MAX_PATH] = "";
  83. snprintf(szPidFile, sizeof(szPidFile) - 1, "%s/%s.pid", MnGetPIDDir(), pszPidFile);
  84. if (unlink(szPidFile) != 0) {
  85. perror(szPidFile);
  86. return (-errno);
  87. }
  88. return (0);
  89. }
  90. static void MnSIGCLD(int iSignal)
  91. {
  92. int iExitStatus;
  93. int iDeadPID;
  94. while ((iDeadPID = wait3(&iExitStatus, WNOHANG, (struct rusage *) NULL)) > 0) {
  95. }
  96. signal(iSignal, MnSIGCLD);
  97. }
  98. static void MnSetupStdHandles(void)
  99. {
  100. int iFD = open(DEVNULL, O_RDWR, 0);
  101. if (iFD == -1) {
  102. MnEventLog("Cannot open file %s : %s", DEVNULL, strerror(errno));
  103. exit(errno);
  104. }
  105. if ((dup2(iFD, 0) == -1) || (dup2(iFD, 1) == -1) || (dup2(iFD, 2) == -1)) {
  106. MnEventLog("File descriptor duplication error : %s", strerror(errno));
  107. exit(errno);
  108. }
  109. close(iFD);
  110. }
  111. static int MnDaemonBootStrap(void)
  112. {
  113. ///////////////////////////////////////////////////////////////////////////////
  114. //  This code is inspired from the code of the great Richard Stevens books.
  115. //  May You RIP in programmers paradise great Richard.
  116. //  I suggest You to buy all his collection, soon !
  117. ///////////////////////////////////////////////////////////////////////////////
  118. #ifdef SIGTTOU
  119. signal(SIGTTOU, SIG_IGN);
  120. #endif
  121. #ifdef SIGTTIN
  122. signal(SIGTTIN, SIG_IGN);
  123. #endif
  124. #ifdef SIGTSTP
  125. signal(SIGTSTP, SIG_IGN);
  126. #endif
  127. ///////////////////////////////////////////////////////////////////////////////
  128. //  1st fork
  129. ///////////////////////////////////////////////////////////////////////////////
  130. int iChildPID = fork();
  131. if (iChildPID < 0) {
  132. MnEventLog("Cannot fork : %s", strerror(errno));
  133. exit(errno);
  134. } else if (iChildPID > 0)
  135. exit(0);
  136. ///////////////////////////////////////////////////////////////////////////////
  137. //  Disassociate from controlling terminal and process group. Ensure the process
  138. //  can't reacquire a new controlling terminal.
  139. ///////////////////////////////////////////////////////////////////////////////
  140. if (setpgrp(0, getpid()) == -1) {
  141. MnEventLog("Can't change process group : %s", strerror(errno));
  142. exit(errno);
  143. }
  144. ///////////////////////////////////////////////////////////////////////////////
  145. //  Lose controlling tty
  146. ///////////////////////////////////////////////////////////////////////////////
  147. int iFdTty = open("/dev/tty", O_RDWR);
  148. if (iFdTty >= 0) {
  149. ioctl(iFdTty, TIOCNOTTY, (char *) NULL);
  150. close(iFdTty);
  151. }
  152. ///////////////////////////////////////////////////////////////////////////////
  153. //  Close open file descriptors
  154. ///////////////////////////////////////////////////////////////////////////////
  155. for (int fd = 0; fd < NOFILE; fd++)
  156. close(fd);
  157. ///////////////////////////////////////////////////////////////////////////////
  158. //  Set std handles
  159. ///////////////////////////////////////////////////////////////////////////////
  160. MnSetupStdHandles();
  161. ///////////////////////////////////////////////////////////////////////////////
  162. //  Probably got set to EBADF from a close
  163. ///////////////////////////////////////////////////////////////////////////////
  164. errno = 0;
  165. ///////////////////////////////////////////////////////////////////////////////
  166. //  Move the current directory to root, to make sure we aren't on a mounted
  167. //  filesystem.
  168. ///////////////////////////////////////////////////////////////////////////////
  169. chdir("/");
  170. ///////////////////////////////////////////////////////////////////////////////
  171. //  Clear any inherited file mode creation mask.
  172. ///////////////////////////////////////////////////////////////////////////////
  173. umask(0);
  174. ///////////////////////////////////////////////////////////////////////////////
  175. //  Ignore childs dead.
  176. ///////////////////////////////////////////////////////////////////////////////
  177. signal(SIGCHLD, MnSIGCLD);
  178. return (0);
  179. }
  180. static int MnIsDebugStartup(int iArgCount, char *pszArgs[])
  181. {
  182. for (int ii = 0; ii < iArgCount; ii++)
  183. if (strcmp(pszArgs[ii], XMAIL_DEBUG_OPTION) == 0)
  184. return (1);
  185. return (0);
  186. }
  187. static int MnDaemonStartup(int iArgCount, char *pszArgs[])
  188. {
  189. ///////////////////////////////////////////////////////////////////////////////
  190. //  Daemon bootstrap code if We're not in debug mode
  191. ///////////////////////////////////////////////////////////////////////////////
  192. if (!MnIsDebugStartup(iArgCount, pszArgs))
  193. MnDaemonBootStrap();
  194. ///////////////////////////////////////////////////////////////////////////////
  195. //  Extract PID file name
  196. ///////////////////////////////////////////////////////////////////////////////
  197. char const *pszPidFile = strrchr(pszArgs[0], '/');
  198. pszPidFile = (pszPidFile != NULL) ? (pszPidFile + 1): pszArgs[0];
  199. ///////////////////////////////////////////////////////////////////////////////
  200. //  Create PID file
  201. ///////////////////////////////////////////////////////////////////////////////
  202. MnSavePID(pszPidFile);
  203. int iServerResult = SvrMain(iArgCount, pszArgs);
  204. ///////////////////////////////////////////////////////////////////////////////
  205. //  Remove PID file
  206. ///////////////////////////////////////////////////////////////////////////////
  207. MnRemovePID(pszPidFile);
  208. return (iServerResult);
  209. }
  210. int main(int iArgCount, char *pszArgs[])
  211. {
  212. return (MnDaemonStartup(iArgCount, pszArgs));
  213. }