Storing result in a file in C++ - c++

I'm writing a program to ping an IP.
I must ping a specific address for 1000s.
Now I want save the TTL to a file to draw it's histogram.
How I can do it? How can I just save the TTL to file?
Here's what I've tried:
#include "stdafx.h"
#include "iostream"
#include "string.h"
#include "stdlib.h"
#include "conio.h"
#include <string>
#include <windows.h>
#include <iostream>
#include <fstream>
using namespace std;
static string host;
static string ping_again;
void ping()
{
cout << "Host: ";
host="www.yahoo.com";
system (("ping " + host).c_str);
}
int main()
{
ping();
return(0);
}

You've chosen to run the ping executable directly with system() and what you are missing is the capture of the output of the command, so you can parse the TTL.
Capturing stdout could have been done with popen instead of system, however, from your list of includes you seem to be on Windows, and that’s where it gets complicated. Check out this question: What is the equivalent to Posix popen() in the Win32 API?, and note that you can call popen if you application is a console application, otherwise the answers will refer you to an MSDN example which painfully details how you should invoke a process and redirect its input/output.
Once you redirect and capture the output you should parse the strings to extract the TTL. Note that the output of ping.exe may be different for different versions of Windows, and that you have little control what ping.exe you are actually invoking.
The alternative and the better approach is to use the ICMP APIs directly instead of invoking a ping executable on hosts where your application runs. Start with IcmpSendEcho and note that it provides the RTT in the reply structure.

Related

Create and Modify System Path Variable

I am creating a C++ Application using Boost Library, so for I have developed modules but stuck here.
I want to Create and modify System Variables(Or Local Environment Variables that persist even after process has terminated) using boost library.
There are methods like
setenv()
putenv()
getenv()
but they make local changes and the value gets disappeared after the process has terminated.
Well that's not the real issue. The real problem arises when i want the same code to run on linux and mac platform.
Can I make a cross platform code using C++ with Libraries that can create and modify and delete the path variables ?
If not
Can I make a code for specific platform say Windows with the above requirements.
As of now I have this code that sets Environment Variable for windows but it give error
#include <string>
#include <iostream>
#include <boost/asio.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <process/boost/process.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/system/error_code.hpp>
namespace bp = boost::process;
namespace bpi = boost::process::initializers;
namespace bio = boost::iostreams;
int main()
{
char* str="SETX Name Value";
bp::pipe p = bp::create_pipe();
{
bio::file_descriptor_sink sink(p.sink, bio::close_handle);
boost::filesystem::path p("C:/Windows/System32/cmd.exe");
boost::system::error_code ec;
bp::windows::execute(bpi::run_exe(p),
bpi::set_cmd_line(str),
bpi::bind_stdout(sink),
bpi::set_on_error(ec)
);
}
bio::file_descriptor_source source(p.source, bio::close_handle);
bio::stream<bio::file_descriptor_source> is(source);
std::string s;
is >> s;
std::cout << s << std::endl;
std::cin.get();
return 0;
}
This has nothing to with Boost, and actually very little with environment variables.
It has to do with System configuration instead.
So, given you have the required permissions to alter the user/system environment you can use these methods to make the changes stick:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx
Most of the samples around favour tools like Windows Scripting Host, PowerShell and .NET to do the job:
Programmatically modifiy environment variables?
But you can probably translate it to C++ if you must.
PS. On Linux, you'd alter some files like /etc/profile, /etc/default/... etc.

Cycle Through URLs

I am writing a small program for my father.
He needs it to cycle through a list of URLs contained in a text file every 15 seconds. I have it opening the URLs but I cant figure out how to either redirect the current tab or close and open a new one.
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <fstream>
#include <iostream>
#include <windows.h>
std::ifstream infile("links.txt");
int main(){
std::string link;
while(std::getline(infile, link)){
system(std::string("start " + link).c_str());
Sleep(15000);
}
}
I am fairly inexperienced with C++ and out of practice. Any and all help is greatly appreciated.
Your first issue is you are calling start on a link which does not exist as a program, this won't work if that is the link to a website. That being said, using system() is very dangerous and slow, this explains it a little better and provides an alternative for windows: https://stackoverflow.com/a/15440094/2671276.

Using a variable across c++ programs (compilations)

this type of question has been asked several times over here and elsewhere but it seems that I don't get any of the solutions to work. What I've 'accomplished' so far is that a variable can be used by two different applications (one application calls the other one via system command) but the value is NOT passed from the main app to the secondary one.
code corresponds to this:
#ifndef avis_h
#define avis_h
#include "string"
using namespace std;
extern int fnu;
#endif
that's the header file avis_h.
The main program goes like this:
#include "stdafx.h"
...
#include "iostream"
#include "avis_h.h"
int fnu;
int main(){fnu=3;system (app2);}
where app2 is the secondary application:
#include "stdafx.h"
...
#include "iostream"
#include "avis_h.h"
int fnu;
int main(){cout<<fnu;Sleep(10);}
instead of the number 3 the number 0 is displayed. I've tried alternative ways but none worked so far. Can somebody please tell me how I get that value passed correctly from the main program to the secondary program?
You can't share variables between independent applications like that.
You can pass it as a parameter to the system command:
//commandLine is app2 + " " + the parameter
system (commandLine);
Breakdown:
std::stringstream ss;
ss << app2;
ss << " ";
ss << fnu;
std::string commandLine = ss.str();
system(commandLine.c_str());
and don't forget to:
#include <sstream>
#include <string>
and retrieve it via argv in the second application.
Or you can use IPC, but that's overkill in this particular case.
Applications have different address spaces and if you wish to pass some data from one application to another you can either write to a file in one application and read the file in another or you can use one of the inter process communication mechanisms supported by the underlying operating system. On Unix-like systems, these mechanisms are pipe, fifo, message queue and shared memory. You can even use sockets. To use the system function is somewhat not very nice. However, if you wish to use system function only, which is workable for this simple inter-process communication, try to pass the value of fnu as a parameter to app2.
char buf [20];
sprintf (buf, "app2 %d", fnu);
system (buf);

How to redirect printf output back into code?

i'm writing a little c++ app to wrap around the opencv haar training function (namely cvCreateTreeCascadeClassifier). The function throws a whole load of output to the console and I wish to parse this output so that I can populate various variables in my code.
The function I wish to use is not part of the actual openCV library; instead it has to be built with my code as part of the project. All of the output from the the function is via printf.
Question: Is it possible to intercept the printf statements before they end up on the console? I've managed to redirect them using freopen but this seems a little clumsy as I then need to parse the file and then delete it when the function call is finished. Also, the function is likely to be running for several hours (and possibly even weeks!) so the size of the file might be an issue if its constantly being appended too.
Requirements: I need this app to be c++ and to run on both windows and linux (but have no problem with conditional compile statements if need be). I would also like to be able to still see my cout and cerr messages on the console (just not the printf).
My googling has removed my will to live! Can anyone help with a solution via either code example or pointers to places I should be looking for an answer?
Thanks
What you can do is:
create a pipe
make the writable end of the pipe the new stdout
read from the readable part of the pipe
Reading and writing should happen in different threads or you risk that your program starves on one end of the pipe.
Here's a sample how to do the redirection in unix & windows:
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
/* gcc defined unix */
#ifdef unix
#include <unistd.h>
#endif
#ifdef WIN32
#include <io.h>
#define pipe(X) _pipe(X,4096,O_BINARY)
#define fileno _fileno
#define dup2 _dup2
#define read _read
#endif
#include <assert.h>
int main()
{
int fds[2];
int res;
char buf[256];
int so;
res=pipe(fds);
assert(res==0);
so=fileno(stdout);
// close stdout handle and make the writable part of fds the new stdout.
res=dup2(fds[1],so);
assert(res!=-1);
printf("Hi there\n");
fflush(stdout);
// reading should happen in a different thread
res=read(fds[0],buf,sizeof(buf)-1);
assert(res>=0 && res<sizeof(buf));
buf[res]=0;
fprintf(stderr,"buf=>%s\n",buf);
return 0;
}
This code should print
buf=>Hi there
(I'm using assert here, because I am too lazy to do real error checking for this example)
Encapsulate the lib into an application, and pipe the application's output to your application. Now write a script so that you don't have to run the apps together every time with a pipe.
Take a look at: http://www.unix.com/programming/136225-reading-stdout-pipe.html it seems promising, but i never tried it.

Redirecting standard output to syslog

I'm planning to package OpenTibia Server for Debian. One of the things I want to do is add startup via /etc/init.d and daemonization of the otserv process.
Thing is, we should probably redirect output to syslog. This is usually done via the syslog() function. Currently, the code is swarmed with:
std::cout << "Stuff to printout" << std::endl;
Is there a proper, easy to add, way to redirect standard output and standard error output into syslog without replacing every single "call" to std::cout and friends?
You can pipe your stdout to syslog with the logger command:
NAME
logger - a shell command interface to the syslog(3) system log module
SYNOPSIS
logger [-isd] [-f file] [-p pri] [-t tag] [-u socket] [message ...]
DESCRIPTION
Logger makes entries in the system log. It provides a shell command
interface to the syslog(3) system log module.
If you don't supply a message on the command line it reads stdin
You can redirect any stream in C++ via the rdbuf() command. This is a bit convoluted to implement but not that hard.
You need to write a streambuf that would output to syslog on overflow(), and replace the std::cout rdbuf with your streambuf.
An example, that would output to a file (no error handling, untested code)
#include <iostream>
#include <fstream>
using namespace std;
int main (int argc, char** argv) {
streambuf * yourStreamBuffer = NULL;
ofstream outputFileStream;
outputFileStream.open ("theOutputFile.txt");
yourStreamBuffer = outputFileStream.rdbuf();
cout.rdbuf(yourStreamBuffer);
cout << "Ends up in the file, not std::cout!";
outputFileStream.close();
return 0;
}
Not sure whether a straight "C" answer suffices; but in "C" you can use underlying stdio features to plug the (FILE*) directly into syslog calls, without an intervening "logger" process. Check out
http://mischasan.wordpress.com/2011/05/25/redirecting-stderr-to-syslog/
Try wrapping the execution of the binary with a suitable script, that just reads stdout and stderr, and send any data read from them on using syslog(). That should work without any code changes in the wrapped application, and be pretty easy.
Not sure if there are existing scripts to pipe into, but writing one shouldn't be hard if not.
I just wrote some code that will do this. It's using ASL instead of syslog, and it's using kevents, so you may need to port it to different APIs for your system (syslog instead of ASL and poll/select instead of kevent)
http://cgit.freedesktop.org/xorg/app/xinit/tree/launchd/console_redirect.c
Furthermore, I basically added this to libsystem_asl on Mountain Lion. Check out the man page for asl_log_descriptor.
Example:
#include <asl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
asl_log_descriptor(NULL, NULL, ASL_LEVEL_INFO, STDOUT_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
asl_log_descriptor(NULL, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
fprintf(stdout, "This is written to stdout which will be at log level info.");
fprintf(stderr, "This is written to stderr which will be at log level notice.");
return 0;
}