In-memory file to intercept stdout on function call - unix

I've inherited this function that I have to call from my code. The function is
from a bizzare library in an arcane programming language -- so I cannot assume
almost anything about it, except for the fact that it prints some useful
infomation to stdout.
Let me simulate its effect with
void black_box(int n)
{
for(int i=0; i<n; i++) std::cout << "x";
std::cout << "\n";
}
I want to intercept and use the stuff it outputs. To that end I redirect stdout
to a temporary file, call the black_box, then restore the stdout and read the
stuff from the temporary file:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
int main(void){
int fd = open( "outbuff", O_RDWR | O_TRUNC | O_CREAT, 0600);
// Redirect stdout to fd
int tmp = dup(1);
dup2( fd, 1);
// Execute
black_box(100);
std::cout << std::flush;
// Restore old stdout
dup2(tmp, 1);
// Read output from the outbuff flie
struct stat st;
fstat(fd, &st);
std::string buf;
buf.resize(st.st_size);
lseek(fd, 0, SEEK_SET);
read(fd, &buf[0], st.st_size);
close(fd);
std::cout << "Captured: " << buf << "\n";
return 0;
}
This works. But creating a file on disk for such a task is not something I'm
proud of. Can I make something like a file, but in-memory?
Before suggesting a pipe, please consider what would happen if
black_box overflows its buffer. And no, I need it single-threaded --
starting an extra process/thread defeats the whole purpose ot what I'm trying
to achieve.

I want to intercept and use the stuff it outputs.
[...] please consider what would happen if black_box overflows its buffer.
I see two alternatives.
If you know the maximum size of the output, and the size is not too excessive, use the socketpair instead of pipe. Unlike pipes, sockets allow to change the size of the egress/ingress buffers.
Use a temporary file on /tmp. In normal case it will not touch disk (unless system is swapping). There are few functions for the purpose, for example mkstemp (or tmpfile).

Related

Qt logical error during getting user's input from terminal via getline function and writing it into a file

Using console, I want to write the desired user's input into a file via getline function inside the wFile function and then read it. I face with logical error during Runtime; whatever I as user write doesn't type into the output terminal and it doesn't succeed more steps. Apparently fwrite function with this feature in the libraries exists, but I want to write my own code differently this way. I think I must have neglected a point. Here's the code:
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QString>
#include <QTextStream>
#include <String>
#include <cstdlib>
using namespace std;
void wFile(QString Filename)
{
QFile mFile(Filename);
QTextStream str(&mFile);
qDebug() << "what do you want to write in the desired file: ";
istream& getline (istream& is, string& str);
if (!mFile.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "could not open the file";
return;
}
mFile.flush();
mFile.close();
}
void read (QString Filename){
QFile nFile(Filename);
if(!nFile.open(QFile::ReadOnly | QFile::Text))
{
qDebug() << "could not open file for reading";
return;
}
QTextStream in(&nFile);
QString nText = in.readAll();
qDebug() << nText;
nFile.close();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString nFilename ="P:/DocumentArminV.txt";
wFile(nFilename);
read(nFilename);
return a.exec();
}
Spoiler alarm: At the very end of this answer, there is a very simple recommendation for a fix.
What OP did
Concerning istream& getline (istream& is, string& str); in wFile(QString Filename):
This declares function getline() in function wFile().
This is a valid declaration concerning C++.
Concerning the sample code, I missed the respective headers. IMHO,
#include <istream> and
#include <string>
are required to make this compiling.
However, it is possible that the existing #includes include them indirectly. So, OP's code may even compile without them.
Declaring functions, which are not used as well as re-declaring functions which are already declared is somehow useless but not wrong.
To demonstrate this, I made a small sample:
#include <cstdio>
#include <istream>
#include <string>
void func()
{
puts("in func()\n");
std::istream& getline(std::istream&, std::string&);
// Even duplicated prototyping is accepted without complaints:
std::istream& getline(std::istream&, std::string&);
}
int main ()
{
func();
return 0;
}
compiles and runs perfectly.
Output:
in func()
Live Demo on coliru
What OP (probably) wanted
Using console, I want to write the desired user's input into a file via getline function inside the wFile function and then read it.
This sounds a bit confusing to me. std::getline(std::cin, ) can be used to read user input from console. May be, it's a bit bad wording only.
Assuming, the OP wanted to read input from console, obviously, declaring a function is not sufficient – it must be called to become effective:
#include <iostream>
void func()
{
std::cout << "Enter file name: ";
std::string fileName; std::getline(std::cin, fileName);
std::cout << "Got file name '" << fileName << "'\n");
}
int main ()
{
func();
return 0;
}
Output:
Enter file name: test.txt↵
Got file name 'test.txt'
Live Demo on coliru
C++ std vs. Qt
Qt is undoubtly built on top of the C++ std library. However, though it's possible it is not recommended to mix both APIs when it can be prevented (or there aren't specific reasons to do so).
Both, Qt and C++ std, are a possibility to write portable software.
Qt covers a lot of things which are provided in the std library as well but a lot of other things additionally which are not or not yet part of std. In some cases, the Qt is a bit less generic but more convenient though this is my personal opinion. IMHO, the following explains how I came to this:
std::string vs. QString
std::string stores a sequence of chars. The meaning of chars when exposed as glyph (e.g. printing on console or displaying in a window) depends on the encoding which is used in this exposing. There are lot of encodings which interprete the numbers in the chars in distinct ways.
Example:
std::string text = "\xc3\xbc";
Decoded/displayed with
Windows-1252: ü
UTF-8: ü
Based on character type of std::string, it is not possible to determine the encoding. Hence, an additional hint must be provided to decode this properly.
(AFAIK, it is similar for std::wstring and wchar_t.)
QString stores a sequence of Unicode characters. So, one universal encoding was chosen by design to mitigate the "encoding hell".
As long as the program operates on QString, no encoding issues should be expected. The same is true when combining QString with other functions of Qt. However, it becomes a bit more complicated when "leaving the Qt universe" – e.g. storing contents of a std::string to QString.
This is the point where the programmer has to provide the additional hint for the encoding of the contents in std::string. QString provides a lot of from...() and to...() methods which can be used to re-encode contents but the application programmer is still responsible to chose the right one.
Assuming that the intended contents of text should have been the ü (i.e. UTF-8 encoding), this can be converted to QString (and back) by:
// std::string (UTF-8) -> QString
std::string text = "\xc3\xbc";
QString qText = QString::fromUtf8(text.c_str());
// QString -> std::string (UTF-8)
std::string text2 = qText.toUtf8();
This has to be considered when input from std::cin shall be passed to QString:
std::cout << "Enter file name: ";
std::string input; std::getline(std::cin, input);
QString qFileName = QString::fromLocal8Bit(input);
And even now, the code contains a little flaw – the locale of std::cin might have changed with std::ios::imbue(). I must admit that I cannot say much more about this. (In daily work, I try to prevent this topic at all e.g. by not relying on Console input which I consider especially critical on Windows – the OS on which we usually deploy to customers.)
Instead, a last note about OP's code:
How to fix it
Remembering my above recommendation (not to mix std and Qt if not necessary), this can be done in Qt exclusively:
QTextStream qtin(stdin);
qtin.readline();
I must admit that I never did it by myself but found this in the Qt forum: Re: stdin reading.

Qt QFile / QTemporaryFile cannot read or write

I have no idea why, but i can´t get the simplest example of QTemporaryFile to run... My real intent is to write data from QAudioInput into a temporary file before it is processed later.
After trying several times I realized that neither .read(), .readLine(), .readAll() or .write() would have any effect... The error string is always "Unknown Error" and it neither works for QFile or QTemporaryFile.
#include <QCoreApplication>
#include <QTemporaryFile>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTemporaryFile tf;
tf.open();
tf.write("Test");
QTextStream in(&tf);
qDebug() << "Testprogramm";
qDebug() << tf.isOpen();
qDebug() << tf.errorString();
qDebug() << in.readLine();
qDebug() << tf.readAll();
tf.close();
return a.exec();
}
The debug posts:
Testprogramm
true
"Unknown error"
""
""
Thank you in advance!
You need to move the file pointer back to the beginning of the file. This has to be done on the file itself when there's no stream on the file, or using the stream when one exists. Also - QFile is a proper C++ class that manages the file resource. There's no need to manually close the file. QFile::~QFile does that job.
The following works just fine:
#include <QtCore>
int main() {
auto line = QLatin1String("Test");
QTemporaryFile tf;
tf.open();
Q_ASSERT(tf.isOpen());
tf.write(line.data());
tf.reset(); // or tf.seek(0)
QTextStream in(&tf);
Q_ASSERT(in.readLine() == line);
in.seek(0); // not in.reset() nor tf.reset()!
Q_ASSERT(in.readLine() == line);
}
The above also demonstrates the following techniques applicable to sscce-style code:
Inclusion of entire Qt module(s). Remember that modules include their dependencies, i.e. #include <QtWidgets> is sufficient by itself.
Absence of main() arguments where unnecessary.
Absence of QCoreApplication instance where unnecessary. You will get clear runtime errors if you need the application instance but don't have one.
Use of asserts to indicate conditions that are expected to be true - that way you don't need to look at the output to verify that it is correct.
Use of QLatin1String over QStringLiteral where ASCII strings need to be compared to both C strings and QStrings. Implicit ASCII casts can be a source of bugs and are discouraged.
QLatin1String is a constant (read-only) wrapper, designed to wrap C string literals - thus there's no need to make line additionally const, although in real projects you'd want to follow the project's style guide here.

checking EOF on unix cp program

I'm writing a unix cp program, but I'm unclear about checking for EOF. The code I have is:
int main(int argc, const char * argv[]) {
int in, out;
char buf[BUFFER_SIZE];
if (argc != 3)
cout << "Error: incorrect number of params" << endl;
if ((in = open(argv[1], O_RDONLY, 0666)) == -1)
cout << "Error: cannot open input file" << endl;
if ((out = open(argv[2], O_WRONLY | O_CREAT, 0666)) == -1)
cout << "Cannot create output file" << endl;
else
while ((read(in, buf, BUFFER_SIZE)) != -1)
write(out, buf, BUFFER_SIZE);
return 0;
}
It reads and writes fine, but writes past EOF when writing the output file. So I get a couple lines of gibberish past the end of the file. Am I just not checking for EOF correctly? I appreciate the input.
You should read the man page for the read function.
On end-of-file, read returns 0. It returns -1 only if there's an error.
read can read fewer bytes than you asked to (and it must do so if there aren't that many bytes remaining to be read). Your write call assumes that read actually read BUFFER_SIZE bytes.
You need to save the result returned by read and write only that many bytes -- and you need to terminate the loop when read returns 0 (indicating end-of-file) or -1 (indicating an error). In the latter case, you should probably do something to handle the error, or at least inform the user.
Incidentally, you don't need the 0666 mode argument when calling open to open the file for reading; that applies only with O_CREAT. Since open is actually a variadic function (like printf), you don't have to supply all the arguments.
The man page is not clear on this point; it pretends that there are two different forms of the open function:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
but in fact that's not legal in C. The POSIX description correctly shows the declaration as:
int open(const char *path, int oflag, ...);

Assign pair of raw pointers returned by a function to unique_ptr

I've looked around a little bit but couldn't find an answer to this.
I have a function returning a pair of pointers to objects, the situation can be simplified to:
#include <iostream>
#include <utility>
#include <memory>
std::pair<int *, int *> shallow_copy()
{
int *i = new int;
int *j = new int;
*i = 5;
*j = 7;
return std::make_pair(i, j);
}
int main(int argc, char *argv[])
{
std::pair<int *, int *> my_pair = shallow_copy();
std::cout << "a = " << my_pair.first << " b = " << *my_pair.second << std::endl;
// This is just creating a newpointer:
std::unique_ptr<int> up(my_pair.first);
std::cout << "a = " << &up << std::endl;
delete my_pair.first;
delete my_pair.second;
return 0;
}
I cannot change the return value of the function. From std::cout << "a = " << &up << std::endl; I can see that the address of the smart pointer is different from the address of the raw pointer.
Is there a way to capture tha std::pair returned by the function in a std::unique_ptr and prevent memory leaks without calling delete explicitly?
NB: The question have been edited to better state the problem and make me look smarter!
You're doing it the right way, but testing it the wrong one. You're comparing the address in first with the address of up. If you print up.get() instead (the address stored in up), you'll find they're equal.
In addition, your code has a double-delete problem. You do delete my_pair.first;, which deallocates the memory block pointed to by my_pair.first and also by up. Then, the destructor of up will deallocate it again when up goes out of scope, resulting in a double delete.
You also asked how to capture both pointers in smart pointers. Since the constructor of std::unique_ptr taking a raw pointer is explicit, you cannot directly do this with a simple std::pair<std::unique_ptr<int>, std::unique_ptr<int>>. You can use a helper function, though:
std::pair<std::unique_ptr<int>, std::unique_ptr<int>> wrapped_shallow_copy()
{
auto orig = shallow_copy();
std::pair<std::unique_ptr<int>, std::unique_ptr<int>> result;
result.first.reset(orig.first);
result.second.reset(orig.second);
return result;
}
Now, use wrapped_shallow_copy() instead of shallow_copy() and you will never leak memory from the call.

C++: OpenSSL, aes cfb encryption [duplicate]

I tried to implement a "very" simple encryption/decryption example. I need it for a project where I would like to encrypt some user information. I can't encrypt the whole database but only some fields in a table.
The database and most of the rest of the project works, except the encryption:
Here is a simplified version of it:
#include <openssl/aes.h>
#include <openssl/evp.h>
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
/* ckey and ivec are the two 128-bits keys necessary to
en- and recrypt your data. Note that ckey can be
192 or 256 bits as well
*/
unsigned char ckey[] = "helloworldkey";
unsigned char ivec[] = "goodbyworldkey";
int bytes_read;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char decryptdata[AES_BLOCK_SIZE];
/* data structure that contains the key itself */
AES_KEY keyEn;
/* set the encryption key */
AES_set_encrypt_key(ckey, 128, &keyEn);
/* set where on the 128 bit encrypted block to begin encryption*/
int num = 0;
strcpy( (char*)indata , "Hello World" );
bytes_read = sizeof(indata);
AES_cfb128_encrypt(indata, outdata, bytes_read, &keyEn, ivec, &num, AES_ENCRYPT);
cout << "original data:\t" << indata << endl;
cout << "encrypted data:\t" << outdata << endl;
AES_cfb128_encrypt(outdata, decryptdata, bytes_read, &keyEn, ivec, &num, AES_DECRYPT);
cout << "input data was:\t" << decryptdata << endl;
return 0;
}
But the output of "decrypted" data are some random characters, but they are the same after every execution of the code. outdata changes with every execution...
I tried to debug and search for a solution, but I couldn't find any solution for my problem.
Now my question, what is going wrong here? Or do I completely misunderstand the provided functions?
The problem is that AES_cfb128_encrypt modifies the ivec (it has to in order to allow for chaining). Your solution is to create a copy of the ivec and initialize it before each call to AES_cfb128_encrypt as follows:
const char ivecstr[AES_BLOCK_SIZE] = "goodbyworldkey\0";
unsigned char ivec[AES_BLOCK_SIZE];
memcpy( ivec , ivecstr, AES_BLOCK_SIZE);
Then repeat the memcpy before your second call to AES_cfb128_encrypt.
Note 1: Your initial vector was a byte too short, so I put an explicit additional \0 at the end of it. You should make sure all of your strings are of the correct length when copying or passing them.
Note 2: Any code which uses encryption should REALLY avoid using strcpy or any other copy of unchecked length. It's a hazard.

Resources