//////////////////////////////////////////////////////////////////////////// // Copyright KAZ 2021 // // // // contact (at) kaz.bzh // // // // This software is a filter to shrink email by attachment extraction. // // // // This software is governed by the CeCILL-B license under French law and // // abiding by the rules of distribution of free software. You can use, // // modify and/or redistribute the software under the terms of the // // CeCILL-B license as circulated by CEA, CNRS and INRIA at the following // // URL "http://www.cecill.info". // // // // As a counterpart to the access to the source code and rights to copy, // // modify and redistribute granted by the license, users are provided // // only with a limited warranty and the software's author, the holder of // // the economic rights, and the successive licensors have only limited // // liability. // // // // In this respect, the user's attention is drawn to the risks associated // // with loading, using, modifying and/or developing or reproducing the // // software by the user in light of its specific status of free software, // // that may mean that it is complicated to manipulate, and that also // // therefore means that it is reserved for developers and experienced // // professionals having in-depth computer knowledge. Users are therefore // // encouraged to load and test the software's suitability as regards // // their requirements in conditions enabling the security of their // // systems and/or data to be ensured and, more generally, to use and // // operate it in the same conditions as regards security. // // // // The fact that you are presently reading this means that you have had // // knowledge of the CeCILL-B license and that you accept its terms. // //////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include "kazDebug.hpp" #include "kazMisc.hpp" using namespace std; using namespace boost; using namespace boost::program_options; using namespace kaz; #define CONSOLE(expr) {if (!quietFlag) {std::cerr << Log::getLocalTimeStr () << " " << expr << std::endl << std::flush; }} // ================================================================================ const string LAST_VERSION_NUM ("3.0"); const string LAST_VERSION_DATE ("2024-01-01"); const string LAST_VERSION (LAST_VERSION_NUM+" "+LAST_VERSION_DATE+" server"); #define PORT 8080 const string BASH ("/bin/bash"); const string FILTER_CMD ("src/bash/testCopyInOut.sh"); // ================================================================================ static options_description mainDescription ("Main options", getCols ()); static options_description hide ("Hidded options", getCols ()); static const char *prog = NULL; // ================================================================================ void usage (const string &msg = "", const bool &hidden = false) { if (!msg.empty ()) { cout << msg << endl; exit (1); } cout << endl << "Usage: " << endl << " " << prog << " [-p port] [-f filterFileName.sh]" << endl << endl << mainDescription << endl; if (hidden) cout << hide << endl; exit (0); } void version () { cout << LAST_VERSION << " KAZ team production (https://kaz.bzh/)" << endl; exit (0); } // ================================================================================ int main (int argc, const char *argv[], char **envp) { // uncomment next line in case of debug parse options // Log::debug = true; DEF_LOG ("main:", LAST_VERSION); prog = argv [0]; bool helpFlag (false), versionFlag (false), quietFlag (false), useTheForceLuke (false), debugFlag (false); int port (PORT); string filterFileName (FILTER_CMD); try { mainDescription.add_options () ("help,h", bool_switch (&helpFlag), "produce this help message") ("version,v", bool_switch (&versionFlag), "display version information") ("quiet,q", bool_switch (&quietFlag), "quiet mode") ("port,p", value (&port)->default_value (port), "server port number") ("filter,f", value (&filterFileName)->default_value (filterFileName), "filter file name script") ; hide.add_options () ("useTheForceLuke", bool_switch (&useTheForceLuke), "display hidded options") ("debug,g", bool_switch (&debugFlag), "debug mode") ; options_description cmd ("All options"); cmd.add (mainDescription).add (hide).add_options (); variables_map vm; store (parse_command_line(argc, argv, cmd), vm); notify (vm); if (debugFlag) { #ifdef DISABLE_LOG cerr << "No debug option available (was compiled with -DDISABLE_LOG)" << endl; #endif } Log::debug = debugFlag; if (useTheForceLuke) usage ("", true); if (versionFlag) version (); if (helpFlag) usage (); } catch (std::exception &e) { cerr << "error: " << e.what() << endl; usage (); return 1; } catch (...) { cerr << "Exception of unknown type!" << endl; return 1; } struct sockaddr_in address; int opt = 1; socklen_t addrlen = sizeof (address); LOG ("create socket"); int serverSocket (socket (AF_INET, SOCK_STREAM, 0)); if (serverSocket < 0) { perror ("socket failed"); exit (EXIT_FAILURE); } LOG ("set socket options"); if (setsockopt (serverSocket, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof (opt))) { perror ("setsockopt"); exit (EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons (port); LOG ("bind"); if (bind (serverSocket, (struct sockaddr*)&address, sizeof (address)) < 0) { perror ("bind failed"); exit (EXIT_FAILURE); } LOG ("listen"); if (listen (serverSocket, 3) < 0) { perror ("listen"); exit (EXIT_FAILURE); } CONSOLE ("Server started on port " << port); for (;;) { LOG ("accept"); int clientSocket (accept (serverSocket, (struct sockaddr*) &address, &addrlen)); if (clientSocket < 0) { perror ("accept"); // XXX ne pas quitter exit (EXIT_FAILURE); } char *command[] = {const_cast (BASH.c_str ()), const_cast (filterFileName.c_str ()), NULL}; switch (fork ()) { case -1: perror ("fork"); exit (EXIT_FAILURE); case 0: CONSOLE ("New request"); close (STDOUT_FILENO); close (STDIN_FILENO); dup2 (clientSocket, STDIN_FILENO); dup2 (clientSocket, STDOUT_FILENO); execve (BASH.c_str (), command, envp); perror ("execve"); break; default: close (clientSocket); break; } } // XXX condition de sortie ? close (serverSocket); return 0; } // ================================================================================