istream from file_descriptor_source (boost::iostreams) or file - c++

I need to do something like this for my program's input:
stream input;
if (decompressed)
input.open(filepath);
else {
file_descriptor=_popen("decompressor "+filepath,"r");
input.open(file_descriptor);
}
input.read(...)
...
I can see one solution - to use _popen in both cases and just copy the file to stdout if it's already decompressed, but this doesn't seem very elegant.
Funny how difficult this is compared with C - I guess the standard library missed it. Now I am lost in the cryptic boost::iostreams documentation. Example code would be great if anyone knows how.

Is this what you're after:
#include <cstdio>
#include <string>
#include <iostream>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
namespace io = boost::iostreams;
int main()
{
bool flag = false;
FILE* handle = 0;
if (flag)
{
handle = _popen("dir", "r");
}
else
{
handle = fopen ("main.cpp", "r");
}
io::stream_buffer<io::file_descriptor_source> fpstream (fileno(handle));
std::istream in (&fpstream);
std::string line;
while (in)
{
std::getline (in, line);
std::cout << line << std::endl;
}
return 0;
}

Adding to jon-hanson's answer, here's a simple example demonstrating how to use file_descriptor_source with a pipe.
How to build:
g++ -m32 -DBOOST_IOSTREAMS_NO_LIB -isystem ${BOOST_PATH}/include \
${BOOST_SRC_PATH}/libs/iostreams/src/file_descriptor.cpp blah.cc -o blah
The code:
#include <fcntl.h>
#include <stdio.h>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
int main( int argc, char* argv[] ) {
// if you just do 'using namespace...', there's a
// namespace collision with the global 'write'
// function used in the child
namespace io = boost::iostreams;
int pipefd[] = {0,0};
pipe( pipefd, 0 ); // If you use O_NONBLOCK, you'll have to
// add some extra checks to the loop so
// it will wait until the child is finished.
if( 0 == fork() ) {
// child
close( pipefd[0] ); // read handle
dup2( pipefd[1], FILENO_STDOUT );
printf( "This\nis\na\ntest\nto\nmake sure that\nit\nis\working as expected.\n" );
return 0; // ya ya, shoot me ;p
}
// parent
close( pipefd[1] ); // write handle
char *buff = new char[1024];
memset( buff, 0, 1024 );
io::stream<io::file_descriptor_source> fds(
io::file_descriptor_source( pipefd[0], io::never_close_handle ) );
// this should work with std::getline as well
while( fds.getline( buff, 1024 )
&& fds.gcount() > 0 // this condition is not enough if you use
// O_NONBLOCK; it should only bail if this
// is false AND the child has exited
) {
printf( "%s,", buff );
}
printf( "\n" );
}

Related

c++ pipe buffering disable

How to disable buffering in pipe. I'm creating a simple recorder/player for I/O. To do this I need record output witch time delays.
To record delays, I need something like this
example tekst
"wait 1s"
example tekst
"wait 1s"
example tekst
...
but if I use
pipe2(in, O_DIRECT );
i see something like this
"wait 100s"
"100 times" example tekst
"wait 100s"
"100 times" example tekst
...
man7 tells:
O_DIRECT (since Linux 3.4)
Create a pipe that performs I/O in "packet" mode. Each
write(2) to the pipe is dealt with as a separate packet, and
read(2)s from the pipe will read one packet at a time.
I tried to disable buffering, by:
fcntl(in[1], F_SETPIPE_SZ, 1);
but it's still not working.
read.cpp
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <assert.h>
bool keep = true;
void intHandler(int dummy) {
keep = 0;
}
int main(void) {
signal(SIGINT, intHandler);
int in[2];
int out[2];
int pid;
int fo;
char buf[1024];
pipe2(in, O_DIRECT );
pipe2(out, O_DIRECT );
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
close(in[0]);
close(out[1]);
close(0);
close(1);
dup2(in[1], 1);
dup2(out[0], 0);
close(in[1]);
close(out[0]);
sleep(1);
char *newargv[] = {"/root/Pulpit/a1", NULL, NULL, NULL};
char *newenviron[] = {NULL};
int ret = execve("/root/Pulpit/a1", newargv, newenviron);
printf("%d", ret);
return 0;
} else {
close(out[0]);
close(in[1]);
int n = 0;
while (keep) {
int wyn = read(in[0], buf, 1024);
if (wyn > 0) {
char aa[1024];
write(1, buf, wyn);
fsync(1);
}
}
}
return (0);
}
a1.cpp
#include <cstdlib>
#include <unistd.h>
#include "stdio.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
while(true){
printf("example text\n");
usleep(100000);
}
return 0;
}

Open TTY to use with execlp and dup

I am trying to create a minimal code to use pipe/fork/execlp.
So far so good, I am using execlp with bash -c, so if I do.
echo asd |./a.out cat
> asd
So it is working as expected.
But if I try to use anything that needs a TTY, it does not work.
Like ./a.out vim, I get "Vim: Warning: Input is not from a terminal"
And the vim that was open does not works as expected.
I tried to find on the internet an example on how to open a TTY, the only one that I found was:
http://www.danlj.org/lad/src/minopen.c
My Code, so far is:
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <unistd.h>
#include <sys/wait.h>
typedef struct pCon{
int fout[2];
int fin[2];
int fd[2];
int pid1, pid2;
} connectionManager;
std::string command = "";
/*
* Implementation
*/
void childFork(connectionManager *cm);
int main(int argc, char *argv[]) {
int size;
if(argc < 2) exit(1);
else command = argv[1];
connectionManager *cm = new connectionManager;
pipe(cm->fd);
if((cm->pid1 = fork()) == -1)exit(1);
if (cm->pid1 == 0)
{
const unsigned int RCVBUFSIZE = 2000;
char echoString[RCVBUFSIZE];
while((size = read(fileno(stdin),echoString,RCVBUFSIZE)) > 0)
write(cm->fd[1], echoString, size);
close(cm->fd[1]);
}
else
childFork(cm);
return 0;
}
void childFork(connectionManager *cm){
char *buffer = new char[2000];
int size;
close(cm->fd[1]);
dup2(cm->fd[0], 0);
close(cm->fd[0]);
pipe(cm->fout);
if((cm->pid2 = fork()) == -1)exit(1);
if (cm->pid2 == 0)
{
close(cm->fout[0]);
int returnCode = execlp("bash", "bash", "-c", command.c_str(), NULL);
if(returnCode!=0)
std::cerr << "Error starting the bash program" << std::endl;
}
else
{
close(cm->fout[1]);
while((size = read(cm->fout[0], buffer, 2000 )) > 0 )
write(fileno(stdout), buffer, size);
}
}
I tried to keep the minimal necessary code to make it work.
Is there any way to implement TTY on this code, I know that does not seems to be such trivial task.
Can someone help me with that?
I also tried to open the tty and dup it, but no luck so far.
Try to use pseudo terminal. You can use opentty. For your purpose you can use forkpty which combines pty with fork. I've created a small example for you. About the same as your program, just it works. I've kept it simple, so I don't handle the terminal control characters.
#include <pty.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>
int main(int argc, char *argv[])
{
if (argc<1) return 1;
int master;
pid_t pid = forkpty(&master, NULL, NULL, NULL); // opentty + login_tty + fork
if (pid < 0) {
return 1; // fork with pseudo terminal failed
}
else if (pid == 0) { // child
char *args[] = { argv[1], argv[2], NULL }; // prg + 1 argument
execvp(argv[1], args); // run the program given in first param
}
else { // parent
struct termios tios;
tcgetattr(master, &tios);
tios.c_lflag &= ~(ECHO | ECHONL);
tcsetattr(master, TCSAFLUSH, &tios);
while(1) {
fd_set read_fd, write_fd, err_fd;
FD_ZERO(&read_fd);
FD_ZERO(&write_fd);
FD_ZERO(&err_fd);
FD_SET(master, &read_fd);
FD_SET(STDIN_FILENO, &read_fd);
select(master+1, &read_fd, &write_fd, &err_fd, NULL);
if (FD_ISSET(master, &read_fd))
{
char ch;
int c;
if (c=read(master, &ch, 1) != -1) // read from program
write(STDOUT_FILENO, &ch, c); // write to tty
else
break; // exit when end of communication channel with program
}
if (FD_ISSET(STDIN_FILENO, &read_fd))
{
char ch;
int c=read(STDIN_FILENO, &ch, 1); // read from tty
write(master, &ch, c); // write to program
}
}
}
return 0;
}
For compiling use -lutil .
While running a new tty device appears in /dev/pts .
vim accepts it as a terminal.

how to create a new folder with increasing its index if it already exist in c++

Pseudo code:
for(int i=0;i<m_iNumOfClass;i++) {
char str[200];
if(iterk doesn't exist)
sprintf(str, "iterk\\HMMtransiMean%d.txt", i);
iter(iterk exist)
mkdir(iterk+1)
sprintf(str, "iterk+1\\HMMtransiMean%d.txt", i);
}
This is pseudo code what i want to do.
I want to create a folder named iterk1 if it doesn't exist. But if it exist, I create a folder named iterk2. and then, create a txt file named HMMtransiMean%d in that folder created just now.
How can i do it? please help me.
If you can use boost::filesystem (as πάντα ῥεῖ advice) then :
#include <string>
#include <fstream>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main()
{
int m_iNumOfClass(2);
path path_template("/tmp"); //Maybe you should use "C:\\tmp" instead
path_template /= "iter";
path directory;
for(int i=0; i<m_iNumOfClass; i++) {
int directory_index = 0;
do
{
directory_index++;
directory = path_template;
directory += std::to_string(directory_index);
} while (!create_directory(directory));
directory /= "HMMtransiMean";
directory += std::to_string(i) + ".txt";
std::string filename(directory.string());
std::ofstream outfile (filename);
outfile.close();
}
return 0;
}
Note: This solution does not require boost...
I assume you're using windows platform (because you use "\\"):
The first useful function to consider is _mkdir (doc).
You can use the non-zero value to determine whether the folder was created.
To create a file you can use fopen (doc)
This works for me on Windows but should work on Linux as well(with a minor include change from direct.h to #include <sys/stat.h>
and #include <sys/types.h> to have mkdir):
#include <iostream>
#include <sstream>
#include <direct.h>
#include <cstdio>
#include <string>
using namespace std;
int main() {
const string pref = "iterk";
string path = pref;
stringstream suffix;
int i=0;
int res = -1;
do{
res = mkdir(path.c_str());
if( res == 0){
path = path + "/HMMtransiMean" + suffix.str() + ".txt";
break;
}
else{
++i;
suffix.str(string());
suffix << i;
path = pref + suffix.str();
}
} while (EEXIST == errno);
FILE * stream;
if( (stream = fopen(path.c_str(), "w+" )) == NULL ) // C4996
printf( "The file was not opened\n" );
else
printf( "The file was opened\n" );
string data = "Hi";
int numwritten = fwrite( data.c_str() , sizeof( char ), data.length() , stream );
printf( "Wrote %d items\n", numwritten );
fclose( stream );
return 0;
}
If you use it on windows only you should probably use the _mkdir function (as I noted before).

How to deactivate input statement after some time?

We know input function or operator (cin, scanf,gets….etc) wait to take input form user & this time has no limit.
Now, I will ask a question & user give the answer, till now there no problem but my problem is “user has a time(may 30 or 40 sec) to give the input, if he fail then input statement will automatically deactivated & execute next statement.”
I think you get my problem. Then please help me in this situation. It will be better if someone give me some really working example code.
I use codebolck 12.11 in windows 7.
An approach for *IX'ish systems (including Cygwin on windows):
You could use alarm() to schedule a SIGALRM, then use read(fileno(stdin), ...).
When the signal arrives read() shall return with -1 and had set errno to EINTR.
Example:
#define _POSIX_SOURCE 1
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
void handler_SIGALRM(int signo)
{
signo = 0; /* Get rid of warning "unused parameter ‘signo’" (in a portable way). */
/* Do nothing. */
}
int main()
{
/* Override SIGALRM's default handler, as the default handler might end the program. */
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler_SIGALRM;
if (-1 == sigaction(SIGALRM, &sa, NULL ))
{
perror("sigaction() failed");
exit(EXIT_FAILURE);
}
}
alarm(2); /* Set alarm to occur in two seconds. */
{
char buffer[16] = { 0 };
int result = read(fileno(stdin), buffer, sizeof(buffer) - 1);
if (-1 == result)
{
if (EINTR != errno)
{
perror("read() failed");
exit(EXIT_FAILURE);
}
printf("Game over!\n");
}
else
{
alarm(0); /* Switch of alarm. */
printf("You entered '%s'\n", buffer);
}
}
return EXIT_SUCCESS;
}
Note: In the example above the blocking call to read() would be interupted on any signal arriving. The code to avoid this is left as an execise to the reader ... :-)
Another Method:
You can use POSIX select() function (and some macros FD_ZERO, FD_SET, FD_ISSET) to check which file descriptors (descriptor number 0 i.e. stdin, in this case) are ready to be read in a given time interval. When they are ready, use appropriate function to read the data (scanf() in this case).
This code might help you understand, what I want to say:
#include <sys/select.h>
#include <sys/time.h>
#include <stdio.h>
#define STDIN 0 // Standard Input File Descriptor
int main()
{
fd_set input; // declare a "file descriptor set" to hold all file descriptors you want to check
int fds, ret_val, num; // fds: Number of file descriptors;
struct timeval tv; // structure to store Timeout value in the format used by select() function
unsigned int timeout = 5; // Your timeout period in seconds
tv.tv_sec = timeout;
tv.tv_usec = 0;
fds = STDIN + 1; // Set number of file decriptors to "1 more than the greatest file descriptor"
// Here, we are using only stdin which is equal to 0
FD_ZERO(&input); // Initialize the set with 0
FD_SET(STDIN, &input); // Add STDIN to set
printf("Enter a number within %d secs\n", timeout);
ret_val = select(fds, &input, NULL, NULL, &tv);
// We need to call select only for monitoring the "input file descriptor set"
// Pass rest of them as NULL
if (ret_val == -1) // Some error occured
perror("select()");
else if (ret_val > 0) // At least one of the file descriptor is ready to be read
{
// printf("Data is available now.\n");
if(FD_ISSET(0, &input)) // Check if stdin is set, here its not necessary as we are using STDIN only
// So ret_val>0 means STDIN is raedy to read
{
scanf("%d", &num);
}
}
else
printf("No data within five seconds.\n"); // select returns zero on timeout
return 0;
}
More Help:
select(2)
You can also try using poll() function available in (again a POSIX standard function) as an alternative to select(). See poll() & poll(2)
#include <cstddef>
#include <ctime>
#include <iostream>
#include <conio.h>
bool get_input ( char *buffer, std::size_t size, int timeout )
{
std::time_t start = std::time ( 0 );
std::size_t n = 0;
for ( ; ; ) {
if ( n == 0 && std::difftime ( std::time ( 0 ), start ) >= timeout )
return false;
if ( kbhit() ) {
if ( n == size - 1 )
break;
char ch = (int)getche();
if ( ch == '\r' ) {
buffer[n++] = '\n';
break;
}
else
buffer[n++] = ch;
}
}
buffer[n] = '\0';
return true;
}
int main()
{
char buffer[512] = {0};
if ( !get_input ( buffer, 512, 5 ) ) {
std::cout<<"Input timed out\n";
buffer[0] = '\n';
}
std::cout<<"input: \""<< buffer <<"\"\n";
}

Is it possible to use a C++ stream class to buffer reads from a pipe?

In short, is it possible to do buffered reads from a pipe from a stream class, along the lines of what this pseudo-example describes.
Please ignore any pedantic problems you see (like not checking errors & the like); I'm doing all that in my real code, this is just a pseudo-example to get across my question.
#include <iostream> // or istream, ifstream, strstream, etc; whatever stream could pull this off
#include <unistd.h>
#include <stdlib.h>
#include <sstream>
void myFunc() {
int pipefd[2][2] = {{0,0},{0,0}};
pipe2( pipefd[0], O_NONBLOCK );
pipe2( pipefd[1], O_NONBLOCK );
if( 0 == fork() ) {
close( pipefd[0][1] );
close( pipefd[1][1] );
dup2( pipefd[0][0], stdout );
dup2( pipefd[1][0], stderr );
execv( /* some arbitrary program */ );
} else {
close( pipefd[0][0] );
close( pipefd[1][0] );
/* cloudy bubble here for the 'right thing to do'.
* Obviously this is faulty code; look at the intent,
* not the implementation.
*/
#ifdef RIGHT_THING_TO_DO
for( int ii = 0; ii < 2; ++ii ) {
cin.tie( pipefd[ii][1] );
do {
cin.readline( /* ... */ );
} while( /* ... */ );
}
#else
// This is what I'm doing now; it works, but I'm
// curious whether it can be done more concisely
do {
do {
select( /* ... */ );
for( int ii = 0; ii < 2; ++ii ) {
if( FD_SET( fd[ii][1], &rfds ) ) {
read( fd[ii][1], buff, 4096 );
if( /* read returned a value > 0 */ ) {
myStringStream << buff;
} else {
FD_CLR( fd[ii][1], &rfds );
}
}
}
} while( /* select returned a value > 0 */ );
} while( 0 == waitpid( -1, 0, WNOHANG ) );
#endif
}
}
Edit
Here's a simple example of how to use boost::file_descriptor to work with a pipe; should work with sockets too, didn't test though.
This is how I compiled it:
g++ -m32 -DBOOST_IOSTREAMS_NO_LIB -isystem ${BOOST_PATH}/include \
${BOOST_SRC_PATH}/libs/iostreams/src/file_descriptor.cpp blah.cc -o blah
Here's the example:
#include <fcntl.h>
#include <stdio.h>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
int main( int argc, char* argv[] ) {
// if you just do 'using namespace...', there's a
// namespace collision with the global 'write'
// function used in the child
namespace io = boost::iostreams;
int pipefd[] = {0,0};
pipe( pipefd, 0 ); // If you use O_NONBLOCK, you'll have to
// add some extra checks to the loop so
// it will wait until the child is finished.
if( 0 == fork() ) {
// child
close( pipefd[0] ); // read handle
dup2( pipefd[1], FILENO_STDOUT );
printf( "This\nis\na\ntest\nto\nmake sure that\nit\nis\working as expected.\n" );
return 0; // ya ya, shoot me ;p
}
// parent
close( pipefd[1] ); // write handle
char *buff = new char[1024];
memset( buff, 0, 1024 );
io::stream<io::file_descriptor_source> fds(
io::file_descriptor_source( pipefd[0], io::never_close_handle ) );
// this should work with std::getline as well
while( fds.getline( buff, 1024 )
&& fds.gcount() > 0 // this condition is not enough if you use
// O_NONBLOCK; it should only bail if this
// is false AND the child has exited
) {
printf( "%s,", buff );
}
printf( "\n" );
}
There sure is. There's an example from the book "The C++ Standard Library: a Tutorial and Reference" for how to make a std::streambuf that wraps file descriptors (like those you get from pipe()). From that creating a stream on top of it is trivial.
Edit: here's the book: http://www.josuttis.com/libbook/
And here's an example output buffer using file descriptors: http://www.josuttis.com/libbook/io/outbuf2.hpp.html
Also, here's an example input buffer: http://www.josuttis.com/libbook/io/inbuf1.hpp.html
You'd want a stream that can be created with an existing file descriptor, or a stream that creates a pipe itself. Unfortunately there's no such standard stream type.
You could write your own or use, for example, boost::iostreams::file_descriptor.
Writing your own entails creating a subclass of basic_streambuf, and then then creating a very simple subclass of basic_i/ostream that does little more than hold your streambuf class and provide convenient constructors.