您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

SendmailIntegrate.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. // /file SendmailIntegrate.cpp
  2. //
  3. // Copyright (C) 2011, ARM Research Labs, LLC.
  4. // See www.armresearch.com for the copyright terms.
  5. //
  6. // This file contains the functions for SendmailIntegrate.
  7. //
  8. // $Id$
  9. //
  10. ///////////////////////////////////////////////////////////////////////////////////////////////////
  11. #include <cstdlib>
  12. #include <cerrno>
  13. #include <cstring>
  14. #include <iostream>
  15. #include <exception>
  16. #include <stdexcept>
  17. #include <sstream>
  18. #include <fstream>
  19. #include "SendmailIntegrate.hpp"
  20. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  21. // Configuration. ////////////////////////////////////////////////////////////////////////////////////////
  22. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  23. const std::string SnfMilterSendmailMcSearchString("Added by SNFMilterConfig");
  24. const std::string SnfMilterSendmailMcIntegrationString("INPUT_MAIL_FILTER(`SNFMilter', `S=unix:/var/snf-milter/socket')dnl # Added by SNFMilterConfig");
  25. const std::string MtaIsRunningCommand("ps axl | grep -v grep | grep -q ' sendmail: '");
  26. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  27. // End of configuration. /////////////////////////////////////////////////////////////////////////////////
  28. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  29. void
  30. SendmailIntegrate::SetOperatingSystem(std::string OperatingSystemType) {
  31. if ("OpenBSD" == OperatingSystemType) {
  32. IntegrationIsSupported = false;
  33. } else if ("FreeBSD" == OperatingSystemType) {
  34. IntegrationIsSupported = false;
  35. } else if ("Ubuntu" == OperatingSystemType) {
  36. IntegrationIsSupported = true;
  37. SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
  38. SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
  39. BuildInstallSendmailCfFile = "(cd /etc/mail && make)";
  40. ReloadMtaCommand = "/etc/init.d/sendmail reload";
  41. FileToBackup.push_back(SendmailSendmailMcPath);
  42. FileToBackup.push_back(SendmailSendmailCfPath);
  43. } else if ("RedHat" == OperatingSystemType) {
  44. IntegrationIsSupported = true;
  45. SendmailSendmailMcPath = "/etc/mail/sendmail.mc";
  46. SendmailSendmailCfPath = "/etc/mail/sendmail.cf";
  47. BuildInstallSendmailCfFile = "(cd /etc/mail && make)";
  48. ReloadMtaCommand = "/etc/init.d/sendmail reload";
  49. FileToBackup.push_back(SendmailSendmailMcPath);
  50. FileToBackup.push_back(SendmailSendmailCfPath);
  51. } else if ("Suse" == OperatingSystemType) {
  52. IntegrationIsSupported = false;
  53. } else {
  54. std::ostringstream Temp;
  55. Temp << "***Error from SendmailIntegrate::SetOperatingSystem: Invalid value of OperatingSystemType: "
  56. << OperatingSystemType;
  57. throw std::runtime_error(Temp.str());
  58. }
  59. }
  60. void
  61. SendmailIntegrate::Integrate(FileBackup *SaveFile) {
  62. if (!IntegrationIsSupported) {
  63. std::ostringstream Temp;
  64. Temp << "Integration with sendmail is not supported on this platform. "
  65. << "Please see " << DOC_DIR << "/INSTALL for instructions for manual "
  66. << "integration with sendmail.";
  67. throw std::runtime_error(Temp.str());
  68. }
  69. if (IsIntegrated()) {
  70. return;
  71. }
  72. if (Verbose()) {
  73. std::cout << "Add to sendmail file " << SendmailSendmailMcPath << ": '"
  74. << SnfMilterSendmailMcIntegrationString << "' and generate new "
  75. << SendmailSendmailCfPath << " file with the command '"
  76. << BuildInstallSendmailCfFile << "'...";
  77. }
  78. if (!Explain()) {
  79. for (FileToBackupType::iterator iFile = FileToBackup.begin(); iFile != FileToBackup.end(); iFile++) {
  80. SaveFile->CreateBackupFile(*iFile); // Save any existing file.
  81. }
  82. std::ofstream Output; // Append the configuration.
  83. Output.open(SendmailSendmailMcPath.c_str(), std::ios::app);
  84. if (!Output) {
  85. std::string Temp;
  86. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  87. Temp += " for writing: ";
  88. Temp += strerror(errno);
  89. throw std::runtime_error(Temp);
  90. }
  91. Output << SnfMilterSendmailMcIntegrationString << "\n";
  92. if (!Output) {
  93. std::string Temp;
  94. Temp = "Error appending to the sendmail configuration file " + SendmailSendmailMcPath;
  95. Temp += ": ";
  96. Temp += strerror(errno);
  97. throw std::runtime_error(Temp);
  98. }
  99. Output.close();
  100. if (!Output) {
  101. std::string Temp;
  102. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  103. Temp += " after appending: ";
  104. Temp += strerror(errno);
  105. throw std::runtime_error(Temp);
  106. }
  107. if (std::system(BuildInstallSendmailCfFile.c_str()) != 0) {
  108. std::string Temp;
  109. Temp = "Error generating sendmail configuration file " + SendmailSendmailCfPath;
  110. throw std::runtime_error(Temp);
  111. }
  112. }
  113. OutputVerboseEnd();
  114. if (!ReloadMta()) {
  115. std::cerr << "Unable to reload the sendmail configuration. Please reload "
  116. << " the sendmail configuration for the integration with SNFMilter to take effect.";
  117. }
  118. }
  119. void
  120. SendmailIntegrate::Unintegrate(FileBackup *SaveFile) {
  121. if (!IntegrationIsSupported) {
  122. return;
  123. }
  124. if (!IsIntegrated()) {
  125. return;
  126. }
  127. std::ifstream Input;
  128. if (Verbose()) {
  129. std::cout << "Remove integration in sendmail file " << SendmailSendmailMcPath
  130. << " and generate new " << SendmailSendmailCfPath << " file with the command '"
  131. << BuildInstallSendmailCfFile << "'--\n";
  132. }
  133. if (!Explain()) {
  134. for (FileToBackupType::iterator iFile = FileToBackup.begin(); iFile != FileToBackup.end(); iFile++) {
  135. SaveFile->CreateBackupFile(*iFile); // Save any existing file.
  136. }
  137. Input.open(SendmailSendmailMcPath.c_str()); // Read the contents.
  138. if (!Input) {
  139. std::string Temp;
  140. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  141. Temp += " for reading: ";
  142. Temp += strerror(errno);
  143. throw std::runtime_error(Temp);
  144. }
  145. std::string Content;
  146. std::string Line;
  147. while (getline(Input, Line)) {
  148. if (std::string::npos != Line.find(SnfMilterSendmailMcSearchString)) { // Check for integration line.
  149. if (Verbose()) {
  150. std::cout << " Remove '" << Line << "'...\n";
  151. }
  152. continue; // Do not copy this line.
  153. }
  154. Content += Line + "\n"; // Copy this line.
  155. }
  156. if (!Input.eof()) { // Should be at end-of-file.
  157. std::string Temp;
  158. Temp = "Error reading the sendmail configuration file " + SendmailSendmailMcPath;
  159. Temp += ": ";
  160. Temp += strerror(errno);
  161. throw std::runtime_error(Temp);
  162. }
  163. Input.close();
  164. if (Input.bad()) {
  165. std::string Temp;
  166. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  167. Temp += " after reading: ";
  168. Temp += strerror(errno);
  169. throw std::runtime_error(Temp);
  170. }
  171. std::ofstream Output; // Write the updated contents.
  172. Output.open(SendmailSendmailMcPath.c_str(), std::ios::trunc);
  173. if (!Output) {
  174. std::string Temp;
  175. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  176. Temp += " for writing: ";
  177. Temp += strerror(errno);
  178. throw std::runtime_error(Temp);
  179. }
  180. Output << Content;
  181. if (!Output) {
  182. std::string Temp;
  183. Temp = "Error writing the sendmail configuration file " + SendmailSendmailMcPath;
  184. Temp += ": ";
  185. Temp += strerror(errno);
  186. throw std::runtime_error(Temp);
  187. }
  188. Output.close();
  189. if (!Output) {
  190. std::string Temp;
  191. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  192. Temp += " after writing: ";
  193. Temp += strerror(errno);
  194. throw std::runtime_error(Temp);
  195. }
  196. if (std::system(BuildInstallSendmailCfFile.c_str()) != 0) { // Rebuild and install the sendmail configuration file.
  197. std::string Temp;
  198. Temp = "Error generating sendmail configuration file " + SendmailSendmailCfPath;
  199. throw std::runtime_error(Temp);
  200. }
  201. }
  202. OutputVerboseEnd();
  203. if (!ReloadMta()) {
  204. std::cerr << "Unable to reload the sendmail configuration. Please run "
  205. << "'sendmail reload' for the integration with SNFMilter to take effect.";
  206. }
  207. }
  208. bool
  209. SendmailIntegrate::MtaIsRunningDetected() {
  210. if (Verbose()) {
  211. std::cout << "Checking whether sendmail is detected to be running...";
  212. }
  213. bool IsRunningDetected;
  214. IsRunningDetected = (std::system(MtaIsRunningCommand.c_str()) == 0);
  215. if (Verbose()) {
  216. std::cout << (IsRunningDetected ? "yes..." : "no...");
  217. }
  218. OutputVerboseEnd();
  219. return IsRunningDetected;
  220. }
  221. bool
  222. SendmailIntegrate::ReloadMta() {
  223. if (!MtaIsRunningDetected()) {
  224. return true;
  225. }
  226. if (Verbose()) {
  227. std::cout << "Reloading sendmail with the command '"
  228. << ReloadMtaCommand << "'...\n";
  229. std::cout.flush();
  230. }
  231. bool Succeeded;
  232. if (!Explain()) {
  233. Succeeded = (std::system(ReloadMtaCommand.c_str()) == 0);
  234. if (Verbose()) {
  235. std::cout << (Succeeded ? "succeeded..." : "failed...");
  236. }
  237. }
  238. OutputVerboseEnd();
  239. return Succeeded;
  240. }
  241. bool
  242. SendmailIntegrate::IsIntegrated() {
  243. if (Verbose()) {
  244. std::cout << "Checking for any SNFMilter integration in the sendmail file " << SendmailSendmailMcPath << "...";
  245. }
  246. if (!FileExists(SendmailSendmailMcPath)) {
  247. if (Verbose()) {
  248. std::cout << "file doesn't exist; sendmail is not integrated...";
  249. }
  250. OutputVerboseEnd();
  251. return false;
  252. }
  253. bool Integrated = false;
  254. std::ifstream Input;
  255. Input.open(SendmailSendmailMcPath.c_str()); // Read the contents.
  256. if (!Input) {
  257. std::string Temp;
  258. Temp = "Error opening the sendmail configuration file " + SendmailSendmailMcPath;
  259. Temp += " for reading: ";
  260. Temp += strerror(errno);
  261. throw std::runtime_error(Temp);
  262. }
  263. std::string Line;
  264. while (getline(Input, Line)) {
  265. if (std::string::npos != Line.find(SnfMilterSendmailMcSearchString)) { // Check for integration line.
  266. Integrated = true; // Found it.
  267. break;
  268. }
  269. }
  270. Input.close();
  271. if (Input.bad()) {
  272. std::string Temp;
  273. Temp = "Error closing the sendmail configuration file " + SendmailSendmailMcPath;
  274. Temp += " after reading: ";
  275. Temp += strerror(errno);
  276. throw std::runtime_error(Temp);
  277. }
  278. if (Verbose()) {
  279. if (Integrated) {
  280. std::cout << "found '" << Line << "'...";
  281. } else {
  282. std::cout << "none found...";
  283. }
  284. }
  285. OutputVerboseEnd();
  286. return Integrated;
  287. }