Creating tar.gz-archive from c++ program does not work - c++

I use the following code snippet for creating a tar.gz-archive in an extensive measurement software. After collecting some data in several files I want to archive and compress them for later use.
Everything works fine when I start the program from the shell, all the data is collected and archived correctly.
However the program should start automatically after system start of an embedded Linux system. When it's started via a script in /etc/init.d, no data files are archived/compressed, even though I get the return value 0. Furthermore, the tar.gz-file is created, but it's empty.
Everything else is working fine.
Can anyone please explain, what I have to do in this special case of an automatic start?
int returnValue = -1;
std::string jobString = RESULT_PATH;
jobString += "/";
jobString += lastJobString;
std::string jobFiles = lastJobString + "*.*";
std::string cmd = "tar cvf - ";
cmd += jobFiles;
cmd += " | gzip > ";
cmd += jobString;
cmd += ".tar.gz";
std::cout << "archiving and compressing " << jobFiles << ": " << cmd << std::flush << std::endl;
returnValue = system(cmd.c_str());
std::cout << "archiving and compressing finished. Code: " << returnValue << std::flush << std::endl;
I know that there are several librariers, like libarchive, libtar, etc. which to use is not as lazy as firing a system command, but I would like to know why this does not work for my case.
Furthermore, the version of tar in my busy box does not support option z.

I finally found a solution for my problem and maybe for all the cases when a system command is called by a daemon:
The trick is to create a new shell by the command sh and change the current directory before the tar-function is called:
std::string cmd = "sh -c \" cd ";
cmd += SOURCE_DIR;
cmd+= " && tar cvf - ";
cmd += jobFiles;
cmd += " | gzip > ";
cmd += jobString;
cmd += ".tar.gz";
returnValue = system(cmd.c_str());
Maybe this will help other users heading to the same problem.

Related

WriteConsole doesn't work with PowerShell ISE?

WriteConsole does not work with PowerShell ISE.
Neither WriteConsoleW or WriteConsoleA do.
See, for example, this program:
#include <iostream>
#include <Windows.h>
void w() {
DWORD written;
BOOL const success = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"Printed\n", 8, &written, nullptr);
std::wcout << (success ? L"Success" : L"Failure") << L". Wrote " << written << L" characters." << std::endl;
}
void a() {
DWORD written;
BOOL const success = WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), "Printed\n", 8, &written, nullptr);
std::cout << (success ? "Success" : "Failure") << ". Wrote " << written << " characters." << std::endl;
}
int main() {
w();
a();
return 0;
}
Ran from PowerShell (or Command Prompt, or Git Bash), it prints:
Printed
Success (wrote 8 characters)
Printed
Success (wrote 8 characters)
But from PowerShell ISE:
Failure (wrote 0 characters)
Failure (wrote 0 characters)
To provide background information on Bertie Wheen's own helpful answer:
Perhaps surprisingly, the Windows PowerShell ISE does not allocate a console by default. (The console-like UI that the ISE presents is not a true Windows console).
A console is allocated on demand, the first time a console-subsystem program is run in a session (e.g., cmd /c ver)
Even once that has happened, however, interactive console-subsystem programs are fundamentally unsupported (try choice /m "Prompt me", for instance).
Interactively, you can test if a console has been allocated or not with the following command: [Console]::WindowTop; if there's no console, you'll get a The handle is invalid error.
It follows from the above that your program cannot assume that a console is present when run in the ISE.
One option is to simply not support running in the ISE, given that it is:
no longer actively developed
and there are various reasons not to use it (bottom section), notably not being able to run PowerShell (Core) 6+, and the limitations with respect to console-subsystem programs mentioned above.
As for a successor environment: The actively developed, cross-platform editor that offers the best PowerShell development experience is Visual Studio Code with its PowerShell extension.
As for the potential reason for the poor console support in the ISE: zett42 notes:
A possible reason why ISE developers choose not to allocate a console could stem from the historic difficulties of creating a custom, embedded console within an app's own window. Developers had to resort to hackish, unsupported ways of doing that. Only recently (2018) Windows got a dedicated pseudo-console (ConPTY) API.
The reason why is shown by this program:
#include <iostream>
#include <Windows.h>
int main() {
DWORD const file_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
if (file_type == FILE_TYPE_CHAR) {
std::cout << "char" << std::endl;
} else if (file_type == FILE_TYPE_PIPE) {
std::cout << "pipe" << std::endl;
} else {
std::cout << file_type << std::endl;
}
return 0;
}
When run from PowerShell (or Command Prompt, or Git Bash), it prints:
char
But from PowerShell ISE:
pipe
WriteConsole cannot write through a pipe, and thus fails. The same thing happens when run from PowerShell / Command Prompt / Git Bash if the output is piped.

how to embedded a linux command example ln -l path1 path2 in cpp

im trying to create a symlink to a path /appdata/config/hello.txt to /appdata/debug/
std::string srcpath = "/appdata/config/hello.txt";
std::string debug = "/appdata/debug/";
In cpp code I have given ln -s srcpath debug
I even tried if(symlink(destPath.c_str(), DEBUG_PATH.c_str()) == 0)
But no luck.
You need to specify the target link name as well, e.g. like this:
std::string fileName = "hello.txt";
std::string srcpath = "/appdata/config/" + fileName;
std::string tgtpath= "/appdata/debug/" + fileName;
if (symlink(srcpath.c_str(), tgtpath.c_str()) != 0) {
std::cerr<< strerror(errno) << std::endl; // #include <errno.h> and <cstring> for this
}
The way you've written it the program will output an "File exists" error message, because you're defining an existing directory as link target.

C++ / R: RInside in Windows 7 machine

This question is related to: C++ and R: Create a .so or .dll plus i have read the questions and replies of these posts:
Compiling RInside programs on Windows
Problem with compiling RInside examples under Windows
I try to run the code provided as an example in the answer provided
#include <RInside.h> // for the embedded R via RInside
#include <iomanip>
int main(int argc, char *argv[]) {
RInside R(argc, argv); // create an embedded R instance
std::string txt = // load library, run regression, create summary
"suppressMessages(require(stats));"
"swisssum <- summary(lm(Fertility ~ . , data = swiss));"
"print(swisssum)";
R.parseEvalQ(txt); // eval command, no return
// evaluate R expressions, and assign directly into Rcpp types
Rcpp::NumericMatrix M( (SEXP) R.parseEval("swcoef <- coef(swisssum)"));
Rcpp::StringVector cnames( (SEXP) R.parseEval("colnames(swcoef)"));
Rcpp::StringVector rnames( (SEXP) R.parseEval("rownames(swcoef)"));
std::cout << "\n\nAnd now from C++\n\n\t\t\t";
for (int i=0; i<cnames.size(); i++) {
std::cout << std::setw(11) << cnames[i] << "\t";
}
std::cout << std::endl;
for (int i=0; i<rnames.size(); i++) {
std::cout << std::setw(16) << rnames[i] << "\t";
for (int j=0; j<cnames.size(); j++) {
std::cout << std::setw(11) << M(i,j) << "\t";
}
std::cout << std::endl;
}
std::cout << std::endl;
exit(0);
}
The error in the CMD is the following
C:\Users\DON\Desktop>R CMD SHLIB final.cpp
g++ -m64 -I"C:/R/R-3.2.4/include" -DNDEBUG -I"d:/RCompile/r-compiling/local/
local323/include" -O2 -Wall -mtune=core2 -c final.cpp -o final.o
final.cpp:1:74: fatal error: RInside.h: No such file or directory
compilation terminated.
make: *** [final.o] Error 1
Warning message:
comando ejecutado 'make -f "C:/R/R-3.2.4/etc/x64/Makeconf" -f "C:/R/R-3.2.4/shar
e/make/winshlib.mk" SHLIB_LDFLAGS='$(SHLIB_CXXLDFLAGS)' SHLIB_LD='$(SHLIB_CXXLD)
' SHLIB="final.dll" WIN=64 TCLBIN=64 OBJECTS="final.o"' tiene estatus 2
Clearly it cant find the RInside.h header. I have the R installed in a folder without spaces. The PATH in global variables have: C:\R\R-3.2.4\bin; C:\Rtools\bin;C:\Rtools\gcc-4.6.3\bin
I understand that in the CMD i cant introduce comands like
$ export PKG_LIBS=‘Rscript -e "Rcpp:::LdFlags()"‘ # if Rcpp older than 0.11.0
$ export PKG_CXXFLAGS=‘Rscript -e "Rcpp:::CxxFlags()"‘
Which first defines and exports two relevant environment variables which R CMD SHLIB then relies on (as put in the FAQ file)
Any advice on this? I need to do a Makefile for each cpp file that i want to compile?
The error is in your approach. You did
R CMD SHLIB final.cpp
which is nowhere given as the correct approach for working with RInside.
Because we need to tell R about headers and libraries for several components, you are supposed to
cd inst/examples/standard
make # build all
or
make rinside_sample3 # build just this
or, if you're on that OS,
make -f Makefile.win # all
or
make -f Makefile.win rinside_sample3
as the Makefile tells R where do find this. That also answers your second question: One Makefile per directory will do. And look at the Makefile: it sets several include directives; your approach only dealt with Rcpp so of course you get an error about RInside.h not found.
I think you keep asking the same question over and over.

QProcess fails to execute a simple console program

I compiled a c++ source file from the Qt app I am creating. Now I want to run the exe file generated and also to redirect its input and output to txt files. But when I try to run it from QProcess, it fails to execute with exit code -2.
This is how I compiled the file using QProcess -
arguments << fileName << "-o" << exeFileName << "-static";
connect(compileProcess, SIGNAL(finished(int)), this, SLOT(compiled()));
compileProcess->start(QString("g++"), arguments);
And this is how I run the exe from QProcess in the slot compiled() -
runProcess->setStandardInputFile(inputFilename);
runProcess->setStandardOutputFile(QFileInfo(exeFileName).path() + "/output.txt");
int code = runProcess->execute(exeFileName); //code = -2
The program runs fine when I start it manually. So, why can't it be started from QProcess?
I am working with Qt 5.0.2 on Windows 7
This is the source file I am compiling -
#include <iostream>
int main() {
std::string s;s
std::cin >> s;
std::cout << s;
return 0;
}
I finally got it to work. The exe file path had spaces in it and Qt did not implicitly add quotes around it. Adding quotes explicitly did the job.
runProcess->start("\"" + exeFileName + "\"");

Unix/C++: Open new terminal and redirect output to it

My program (C++ on Solaris 10) writes output via wcout to its terminal when it is started from a shell. But when I execute it from within Sun Studio or the file manager is does not have a terminal and the ouput appears in the Sun Studio output window or nowhere at all.
I would like it to open its own terminal window in any of the three cases and attach wcout to this terminal window. I want this to be done be the program itself with C++ system calls not by the way how the program is executed from some shell or script. Because then execution in the Studio IDE and double-click in the file manager would still have the same effect.
Being a Windows programmer that seems quite natural to me but I could not find out how this is done in my Unix books nor in the web. Am I requesting the wrong thing, is it really so hard to do or am I missing something?
The following is close to what you want. It still has a few bugs:
The xterm cannot be normally closed (it closes when the program terminates, though). I have no idea why this is so.
Before the intended output, a number is output. Again, I have no idea why.
I don't seem to be able to redirect input.
Maybe someone else know how to fix those bugs (and any others I might not have noticed).
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <sstream>
int main()
{
int pt = posix_openpt(O_RDWR);
if (pt == -1)
{
std::cerr << "Could not open pseudo terminal.\n";
return EXIT_FAILURE;
}
char* ptname = ptsname(pt);
if (!ptname)
{
std::cerr << "Could not get pseudo terminal device name.\n";
close(pt);
return EXIT_FAILURE;
}
if (unlockpt(pt) == -1)
{
std::cerr << "Could not get pseudo terminal device name.\n";
close(pt);
return EXIT_FAILURE;
}
std::ostringstream oss;
oss << "xterm -S" << (strrchr(ptname, '/')+1) << "/" << pt << " &";
system(oss.str().c_str());
int xterm_fd = open(ptname,O_RDWR);
char c;
do read(xterm_fd, &c, 1); while (c!='\n');
if (dup2(pt, 1) <0)
{
std::cerr << "Could not redirect standard output.\n";
close(pt);
return EXIT_FAILURE;
}
if (dup2(pt, 2) <0)
{
std::cerr << "Could not redirect standard error output.\n";
close(pt);
return EXIT_FAILURE;
}
std::cout << "This should appear on the xterm." << std::endl;
std::cerr << "So should this.\n";
std::cin.ignore(1);
close(pt);
return EXIT_SUCCESS;
}
You want to output to a file (redirect, using a logging API or close stdout/reopen it as a file). And then tail it with tail -f in a terminal of your choice.
This has added benefit of saving your log output for review even if the terminal crashes/is killed.
When you invoke your program, instead of running: myprog 1 2 3 a b c, run xterm -e myprog 1 2 3 a b c.
I would recommnend to create a shell script that runs the terminal to which you pass your program to execute, then you should call that script instead of your program from the file manager.
Your script.sh:
#!/bin/sh
xterm -e /path_to_your_program/your_program
Using mknod to create pipe in /tmp every linux have /tmp and everyone always allowed to use it
system("mknod /tmp/printing_pipe pipe");
system("qterminal -e tail -f /tmp/printing_pipe");
write to the /tmp/printing_pipe to use it