diff --git a/Makefile b/Makefile index 575f0fa..448d7de 100644 --- a/Makefile +++ b/Makefile @@ -44,11 +44,23 @@ OUT_DIR = $(BLD_DIR)/out LIB_DIR = $(BLD_DIR)/lib OBJ_DIR = $(BLD_DIR)/obj -KAZ_PRG = eMailShrinker -KAZ_MOD = eMailShrinker EmbeddedData Attachment MainAttachment SizeArg kazDebug kazMisc -KAZ_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(KAZ_MOD)) -KAZ_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(KAZ_MOD)) -KAZ_OUT = $(patsubst %, $(OUT_DIR)/%, $(KAZ_PRG)) +EMS_PRG = eMailShrinker +EMS_MOD = eMailShrinker EmbeddedData Attachment MainAttachment SizeArg kazDebug kazMisc +EMS_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(EMS_MOD)) +EMS_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(EMS_MOD)) +EMS_OUT = $(patsubst %, $(OUT_DIR)/%, $(EMS_PRG)) + +SRV_PRG = server +SRV_MOD = server kazDebug kazMisc +SRV_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(SRV_MOD)) +SRV_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(SRV_MOD)) +SRV_OUT = $(patsubst %, $(OUT_DIR)/%, $(SRV_PRG)) + +TSRV_PRG = testServerRW +TSRV_MOD = testServerRW kazDebug +TSRV_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(TSRV_MOD)) +TSRV_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(TSRV_MOD)) +TSRV_OUT = $(patsubst %, $(OUT_DIR)/%, $(TSRV_PRG)) ## FLAGS ############################### @@ -65,12 +77,22 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/*/%.cpp $(CC) $< $(IFLAGS) -cpp -c -o $@ ## ENTRIES ############################# -all: init eMailShrinker doc +all: init $(EMS_PRG) $(SRV_PRG) $(TSRV_PRG) doc -eMailShrinker: $(KAZ_OUT) +$(EMS_PRG): $(EMS_OUT) -$(KAZ_OUT): $(KAZ_OBJ) - $(CC) $(KAZ_OBJ) $(IFLAGS) -cpp -L$(LIB_DIR) $(LFLAGS) -o $@ +$(EMS_OUT): $(EMS_OBJ) + $(CC) $(EMS_OBJ) $(IFLAGS) -cpp -L$(LIB_DIR) $(LFLAGS) -o $@ + +$(SRV_PRG): $(SRV_OUT) + +$(SRV_OUT): $(SRV_OBJ) + $(CC) $(SRV_OBJ) $(IFLAGS) -cpp -L$(LIB_DIR) $(LFLAGS) -o $@ + +$(TSRV_PRG): $(TSRV_OUT) + +$(TSRV_OUT): $(TSRV_OBJ) + $(CC) $(TSRV_OBJ) $(IFLAGS) -cpp -L$(LIB_DIR) $(LFLAGS) -o $@ doc: doxygen src/Doxyfile @@ -86,8 +108,8 @@ wipe: clean -rm -rf $(OUT_DIR) $(LIB_DIR) $(BLD_DIR) ## DEPENDS ############################# -ALL_OUT = $(KAZ_PRG) $(JIR_PRG) -ALL_OBJ = $(KAZ_OBJ) $(JIR_OBJ) +ALL_OUT = $(EMS_PRG) $(SRV_PRG) $(TSRV_PRG) +ALL_OBJ = $(EMS_OBJ) $(SRV_OBJ) $(TSRV_OBJ) DEPENDS = ${ALL_OUT:=.d} ${ALL_OBJ:.o=.d} -include ${DEPENDS} diff --git a/src/bash/testCopyInOut.sh b/src/bash/testCopyInOut.sh new file mode 100644 index 0000000..1f6e97b --- /dev/null +++ b/src/bash/testCopyInOut.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +TMP_LOG="$(mktemp)" + +#trap "rm -rf ${TMP_LOG}" 0 1 2 3 15 + +cat > ${TMP_LOG} +cat ${TMP_LOG} diff --git a/src/cpp/server.cpp b/src/cpp/server.cpp new file mode 100644 index 0000000..9031bb5 --- /dev/null +++ b/src/cpp/server.cpp @@ -0,0 +1,223 @@ +//////////////////////////////////////////////////////////////////////////// +// 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; +} + +// ================================================================================ diff --git a/src/cpp/testServerRW.cpp b/src/cpp/testServerRW.cpp new file mode 100644 index 0000000..6cc8a07 --- /dev/null +++ b/src/cpp/testServerRW.cpp @@ -0,0 +1,118 @@ +//////////////////////////////////////////////////////////////////////////// +// 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 "kazDebug.hpp" + +using namespace std; +using namespace kaz; + +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+" testServerRW"); + +#define PORT 8080 + +int +main (int argc, char const* argv[]) { + Log::debug = true; + DEF_LOG ("main:", LAST_VERSION); + + int clientSocket; + struct sockaddr_in serv_addr; + LOG ("create socket"); + if ((clientSocket = socket (AF_INET, SOCK_STREAM, 0)) < 0) { + cerr << endl << "Socket creation error" << endl; + perror ("socket failed"); + return -1; + } + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons (PORT); + + LOG ("check address"); + if (inet_pton (AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) { + cerr << endl << "Invalid address / Address not supported" << endl; + perror ("socket failed"); + return -1; + } + + LOG ("connect on " << PORT); + if (connect (clientSocket, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { + cerr << endl << "Connection Failed" << endl; + perror ("socket failed"); + return -1; + } + + bool end (false); + LOG ("send original email (end with QUIT)"); + for (;;) { + if (!end) { + string hello; + cin >> hello; + if (hello == "QUIT") { + shutdown (clientSocket, SHUT_WR); + LOG ("shutdown send"); + break; + } + LOG ("avant"); + hello.push_back ('\n'); + send (clientSocket, hello.c_str (), hello.size (), 0); + LOG ("apres"); + } + } + LOG ("receive..."); + for (;;) { + char buffer[1024] = { 0 }; + ssize_t msgSize (recv (clientSocket, buffer, 1024 - 1, 0)); + switch (msgSize) { + case -1 : + perror ("socket failed"); + return -1; + case 0 : + LOG ("shutdown receive"); + close (clientSocket); + return 0; + break; + default: + //cout.write (buffer, msgSize); + printf ("%s\n", buffer); + } + } +}