kopia lustrzana https://github.com/jamescoxon/dl-fldigi
481 wiersze
13 KiB
C++
481 wiersze
13 KiB
C++
// ----------------------------------------------------------------------------
|
|
// rx_extract.cxx extract delineated data stream to file
|
|
//
|
|
// Copyright 2009 W1HKJ, Dave Freese
|
|
//
|
|
// This file is part of fldigi.
|
|
//
|
|
// Fldigi 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 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Fldigi 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 fldigi. If not, see <http://www.gnu.org/licenses/>.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include <config.h>
|
|
|
|
#include <unistd.h>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <string>
|
|
|
|
#include <FL/filename.H>
|
|
#include "fileselect.h"
|
|
|
|
#include "gettext.h"
|
|
#include "rx_extract.h"
|
|
#include "main.h"
|
|
#include "status.h"
|
|
#include "fl_digi.h"
|
|
#include "configuration.h"
|
|
#include "confdialog.h"
|
|
#include "debug.h"
|
|
#include "icons.h"
|
|
#include "qrunner.h"
|
|
#include "timeops.h"
|
|
#include "xmlrpc.h"
|
|
|
|
using namespace std;
|
|
|
|
static const char *wrap_beg = "[WRAP:beg]";
|
|
static const char *wrap_end = "[WRAP:end]";
|
|
static const char *flmsg = "<flmsg>";
|
|
|
|
static const char flamp_beg[] = ">FLAMP";
|
|
static const char flamp_end[] = ":EOT}";
|
|
|
|
#ifdef __WIN32__
|
|
const char *txtWrapInfo = _("\
|
|
Detect the occurance of [WRAP:beg] and [WRAP:end]\n\
|
|
Save tags and all enclosed text to date-time stamped file, ie:\n\
|
|
NBEMS.files\\WRAP\\recv\\extract-20090127-092515.wrap");
|
|
#else
|
|
const char *txtWrapInfo = _("\
|
|
Detect the occurance of [WRAP:beg] and [WRAP:end]\n\
|
|
Save tags and all enclosed text to date-time stamped file, ie:\n\
|
|
~/.nbems/WRAP/recv/extract-20090127-092515.wrap");
|
|
#endif
|
|
|
|
#define bufsize 64
|
|
char rx_extract_buff[bufsize + 1];
|
|
string rx_buff;
|
|
string rx_extract_msg;
|
|
|
|
bool extract_wrap = false;
|
|
bool extract_flamp = false;
|
|
bool extract_arq = false;
|
|
|
|
bool bInit = false;
|
|
|
|
char dttm[64];
|
|
|
|
void rx_extract_reset()
|
|
{
|
|
rx_buff.clear();
|
|
memset(rx_extract_buff, ' ', bufsize);
|
|
rx_extract_buff[bufsize] = 0;
|
|
extract_wrap = false;
|
|
extract_flamp = false;
|
|
extract_arq = false;
|
|
put_status("");
|
|
}
|
|
|
|
void rx_extract_timer(void *)
|
|
{
|
|
rx_extract_msg = "Extract timed out";
|
|
put_status(rx_extract_msg.c_str(), 20, STATUS_CLEAR);
|
|
rx_extract_reset();
|
|
}
|
|
|
|
void rx_add_timer()
|
|
{
|
|
Fl::add_timeout(progdefaults.extract_timeout, rx_extract_timer, NULL);
|
|
}
|
|
|
|
void rx_remove_timer()
|
|
{
|
|
Fl::remove_timeout(rx_extract_timer);
|
|
}
|
|
|
|
void invoke_flmsg()
|
|
{
|
|
string cmd = progdefaults.flmsg_pathname;
|
|
|
|
REQ(rx_remove_timer);
|
|
struct tm tim;
|
|
time_t t;
|
|
time(&t);
|
|
gmtime_r(&t, &tim);
|
|
strftime(dttm, sizeof(dttm), "%Y%m%d-%H%M%S", &tim);
|
|
|
|
string outfilename = FLMSG_WRAP_recv_dir;
|
|
outfilename.append("extract-");
|
|
outfilename.append(dttm);
|
|
outfilename.append(".wrap");
|
|
ofstream extractstream(outfilename.c_str(), ios::binary);
|
|
if (extractstream) {
|
|
extractstream << rx_buff;
|
|
extractstream.close();
|
|
}
|
|
rx_extract_msg = "File saved in ";
|
|
rx_extract_msg.append(FLMSG_WRAP_recv_dir);
|
|
put_status(rx_extract_msg.c_str(), 20, STATUS_CLEAR);
|
|
|
|
if (flmsg_online && progdefaults.flmsg_transfer_direct) {
|
|
guard_lock autolock(server_mutex);
|
|
flmsg_data.append(rx_buff);
|
|
return;
|
|
}
|
|
|
|
if (progdefaults.open_nbems_folder)
|
|
open_recv_folder(FLMSG_WRAP_recv_dir.c_str());
|
|
|
|
if ((progdefaults.open_flmsg || progdefaults.open_flmsg_print) &&
|
|
(rx_buff.find(flmsg) != string::npos) &&
|
|
!progdefaults.flmsg_pathname.empty()) {
|
|
|
|
#ifdef __MINGW32__
|
|
cmd.append(" -title ").append(dttm);
|
|
cmd.append(" --flmsg-dir ").append("\"").append(FLMSG_dir).append("\"");
|
|
|
|
if (progdefaults.open_flmsg_print && progdefaults.open_flmsg)
|
|
cmd.append(" --b");
|
|
else if (progdefaults.open_flmsg_print)
|
|
cmd.append(" --p");
|
|
cmd.append(" \"").append(outfilename).append("\"");
|
|
char *cmdstr = strdup(cmd.c_str());
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
memset(&si, 0, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
memset(&pi, 0, sizeof(pi));
|
|
if (!CreateProcess( NULL, cmdstr,
|
|
NULL, NULL, FALSE,
|
|
CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
|
LOG_ERROR("CreateProcess failed with error code %ld", GetLastError());
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
free (cmdstr);
|
|
#else
|
|
string params = "";
|
|
static string ap[10];// = cmd;//"";
|
|
string param = "";
|
|
|
|
size_t p = cmd.find(" -");
|
|
if (p != string::npos) {
|
|
param.assign(cmd.substr(p));
|
|
cmd = cmd.substr(0,p);
|
|
}
|
|
for (int i = 0; i < 10; i++) ap[i].clear();
|
|
|
|
int n = 0;
|
|
ap[n++] = "-title"; ap[n++] = dttm;
|
|
ap[n++] = "--flmsg-dir"; ap[n++] = FLMSG_dir;
|
|
if (progdefaults.open_flmsg_print && progdefaults.open_flmsg)
|
|
ap[n++] = " --b";//params = " --b";
|
|
else if (progdefaults.open_flmsg_print)
|
|
ap[n++] = " --p";//params = " --p";
|
|
ap[n++] = outfilename;
|
|
|
|
switch (fork()) {
|
|
case 0:
|
|
# ifndef NDEBUG
|
|
unsetenv("MALLOC_CHECK_");
|
|
unsetenv("MALLOC_PERTURB_");
|
|
# endif
|
|
switch (n) {
|
|
case 1:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 2:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 3:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 4:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(), (char*)ap[3].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 5:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(), (char*)ap[3].c_str(),
|
|
(char*)ap[4].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 6:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(), (char*)ap[3].c_str(),
|
|
(char*)ap[4].c_str(), (char*)ap[5].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 7:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(), (char*)ap[3].c_str(),
|
|
(char*)ap[4].c_str(), (char*)ap[5].c_str(),
|
|
(char*)ap[6].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 8:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(), (char*)ap[3].c_str(),
|
|
(char*)ap[4].c_str(), (char*)ap[5].c_str(),
|
|
(char*)ap[6].c_str(), (char*)ap[7].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 9:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(), (char*)ap[3].c_str(),
|
|
(char*)ap[4].c_str(), (char*)ap[5].c_str(),
|
|
(char*)ap[6].c_str(), (char*)ap[7].c_str(),
|
|
(char*)ap[8].c_str(),
|
|
(char*)0);
|
|
break;
|
|
case 10:
|
|
execlp(
|
|
(char*)cmd.c_str(), (char*)cmd.c_str(),
|
|
(char*)ap[0].c_str(), (char*)ap[1].c_str(),
|
|
(char*)ap[2].c_str(), (char*)ap[3].c_str(),
|
|
(char*)ap[4].c_str(), (char*)ap[5].c_str(),
|
|
(char*)ap[6].c_str(), (char*)ap[7].c_str(),
|
|
(char*)ap[8].c_str(), (char*)ap[9].c_str(),
|
|
(char*)0);
|
|
break;
|
|
default : ;
|
|
}
|
|
exit(EXIT_FAILURE);
|
|
case -1:
|
|
fl_alert2(_("Could not start flmsg"));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void start_flmsg()
|
|
{
|
|
string cmd = progdefaults.flmsg_pathname;
|
|
|
|
#ifdef __MINGW32__
|
|
char *cmdstr = strdup(cmd.c_str());
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
memset(&si, 0, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
memset(&pi, 0, sizeof(pi));
|
|
if (!CreateProcess( NULL, cmdstr,
|
|
NULL, NULL, FALSE,
|
|
CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
|
LOG_ERROR("CreateProcess failed with error code %ld", GetLastError());
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
free (cmdstr);
|
|
#else
|
|
switch (fork()) {
|
|
case 0:
|
|
execlp((char*)cmd.c_str(), (char*)cmd.c_str(), (char*)0, (char*)0);
|
|
exit(EXIT_FAILURE);
|
|
case -1:
|
|
fl_alert2(_("Could not start flmsg"));
|
|
default: ;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void rx_extract_add(int c)
|
|
{
|
|
if (!c) return;
|
|
check_nbems_dirs();
|
|
|
|
if (!bInit) {
|
|
rx_extract_reset();
|
|
bInit = true;
|
|
}
|
|
char ch = (char)c;
|
|
|
|
memmove(rx_extract_buff, &rx_extract_buff[1], bufsize - 1);
|
|
rx_extract_buff[bufsize - 1] = ch;
|
|
|
|
if (strstr(rx_extract_buff, "~1") && strstr(rx_extract_buff, "~4")) {
|
|
if (!flmsg_online) start_flmsg();
|
|
memset(rx_extract_buff, ' ', bufsize);
|
|
return;
|
|
}
|
|
if (!extract_arq && strstr(rx_extract_buff, "ARQ:FILE::FLMSG_XFR")) {
|
|
extract_arq = true;
|
|
REQ(rx_remove_timer);
|
|
REQ(rx_add_timer);
|
|
memset(rx_extract_buff, ' ', bufsize);
|
|
rx_extract_msg = "Extracting ARQ msg";
|
|
put_status(rx_extract_msg.c_str());
|
|
return;
|
|
} else if (extract_arq) {
|
|
REQ(rx_remove_timer);
|
|
REQ(rx_add_timer);
|
|
if (strstr(rx_extract_buff, "ARQ::ETX"))
|
|
rx_extract_reset();
|
|
return;
|
|
} else if (!extract_flamp && strstr(rx_extract_buff, flamp_beg)) {
|
|
extract_flamp = true;
|
|
memset(rx_extract_buff, ' ', bufsize);
|
|
rx_extract_msg = "Extracting FLAMP";
|
|
put_status(rx_extract_msg.c_str());
|
|
return;
|
|
} else if (extract_flamp) {
|
|
REQ(rx_remove_timer);
|
|
REQ(rx_add_timer);
|
|
if (strstr(rx_extract_buff, flamp_end) != NULL)
|
|
rx_extract_reset();
|
|
return;
|
|
} else if (!extract_wrap && strstr(rx_extract_buff, wrap_beg)) {
|
|
rx_buff.assign(wrap_beg);
|
|
rx_extract_msg = "Extracting WRAP/FLMSG";
|
|
put_status(rx_extract_msg.c_str());
|
|
extract_wrap = true;
|
|
REQ(rx_remove_timer);
|
|
REQ(rx_add_timer);
|
|
return;
|
|
} else if (extract_wrap) {
|
|
rx_buff += ch;
|
|
REQ(rx_remove_timer);
|
|
REQ(rx_add_timer);
|
|
if (strstr(rx_extract_buff, wrap_end) != NULL) {
|
|
invoke_flmsg();
|
|
rx_extract_reset();
|
|
}
|
|
}
|
|
}
|
|
|
|
void select_flmsg_pathname()
|
|
{
|
|
txt_flmsg_pathname->value(progdefaults.flmsg_pathname.c_str());
|
|
txt_flmsg_pathname->redraw();
|
|
|
|
#ifdef __APPLE__
|
|
open_recv_folder("/Applications/");
|
|
return;
|
|
#else
|
|
string deffilename = progdefaults.flmsg_pathname;
|
|
if (deffilename.empty())
|
|
# ifdef __MINGW32__
|
|
deffilename = "C:\\Program Files\\";
|
|
const char *p = FSEL::select(_("Locate flmsg executable"), _("flmsg.exe\t*.exe"), deffilename.c_str());
|
|
# else
|
|
deffilename = "/usr/local/bin/";
|
|
const char *p = FSEL::select(_("Locate flmsg executable"), _("flmsg\t*"), deffilename.c_str());
|
|
# endif
|
|
if (!p) return;
|
|
if (!*p) return;
|
|
|
|
progdefaults.flmsg_pathname = p;
|
|
progdefaults.changed = true;
|
|
txt_flmsg_pathname->value(p);
|
|
|
|
#endif
|
|
}
|
|
|
|
// this only works on Linux and Unix
|
|
// not Windoze or
|
|
// OS X to find binaries in the /Applications/ directory structure
|
|
|
|
bool find_pathto_exectable(string &binpath, string executable)
|
|
{
|
|
size_t endindex = 0;
|
|
|
|
binpath.clear();
|
|
|
|
// Get the PATH environment variable as pointer to string
|
|
// The strings in the environment list are of the form name=value.
|
|
// As typically implemented, getenv() returns a pointer to a string within
|
|
// the environment list. The caller must take care not to modify this string,
|
|
// since that would change the environment of the process.
|
|
//
|
|
// The implementation of getenv() is not required to be reentrant. The string
|
|
// pointed to by the return value of getenv() may be statically allocated, and
|
|
// can be modified by a subsequent call to getenv(), putenv(3), setenv(3), or
|
|
// unsetenv(3).
|
|
|
|
char *environment = getenv("PATH");
|
|
|
|
if (environment == NULL) return false;
|
|
|
|
string env = environment;
|
|
string testpath = "";
|
|
|
|
char endchar = ':';
|
|
|
|
// Parse single PATH string into directories
|
|
while (!env.empty()) {
|
|
endindex = env.find(endchar);
|
|
testpath = env.substr(0, endindex);
|
|
|
|
testpath.append("/"); // insert linux, unix, osx OS-correct delimiter
|
|
testpath.append(executable); // append executable name
|
|
|
|
// Most portable way to check if a file exists: Try to open it.
|
|
FILE *checkexists = NULL;
|
|
checkexists = fopen( testpath.c_str(), "r" ); // try to open file readonly
|
|
if (checkexists) { // if the file successfully opened, it exists.
|
|
fclose(checkexists);
|
|
binpath = testpath;
|
|
return true;
|
|
}
|
|
if (endindex == string::npos)
|
|
env.clear();
|
|
else
|
|
env.erase(0, endindex + 1);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
string select_binary_pathname(string deffilename)
|
|
{
|
|
#ifdef __APPLE__
|
|
open_recv_folder("/Applications/");
|
|
return "";
|
|
#else
|
|
# ifdef __MINGW32__
|
|
deffilename = "C:\\Program Files\\";
|
|
const char *p = FSEL::select(_("Locate executable"), _("*.exe"), deffilename.c_str());
|
|
# else
|
|
deffilename = "/usr/local/bin/";
|
|
const char *p = FSEL::select(_("Locate binary"), _("*"), deffilename.c_str());
|
|
# endif
|
|
string executable = "";
|
|
if (p && *p) executable = p;
|
|
// do not allow recursion !!
|
|
if (executable.find("fldigi") != string::npos) return "";
|
|
return executable;
|
|
#endif
|
|
}
|
|
|