How to find the computer's domain programatically - c++

Most of the systems currently are attached to a domain or so. Is there any method/system call I can make to get the system current domain (Something similar to gethostname). I am mainly looking for some portable solution (win/Lin) but if you can direct me how I can get the info in Linux it will be greatly helpful. I am trying to acquire the same in a C++ program in Linux, but have not yet been able.
Just to clarify, I know we can get the hostname easily. It the "somedomain" part of the "localhost#somedomain" I am looking for.

There's a getdomainname() function, that gets the DNS domain name of your computer (not the workgroup/Windows domain), e.g.:
#include <iostream>
#include <unistd.h>
int main() {
char buffer[1024];
getdomainname(buffer, sizeof(buffer));
std::cout << buffer << std::endl;
}

Related

boost::filesystem::relative() cannot access the file because it is being used by another process

When accessing some network drives, the functions relative(path, base_path) and canonical(path, base_path) throw an exception. The message is always:
The process cannot access the file because it is being used by another process
I've observed this behavior only on some shared network drives that were operated by our IT department and contain symbolic links. I was not able to provoke the same issue on local drives or on shared drives from an adjacent computer. Our suspicion is that the archive/backup solution used on the network drives is also a driver here. The known factors are these so far:
The drive must be a network share (drive etc.)
The path needs to contain a symbolic link component
The drive operates under a backup/archive solution
My questions are:
is this a potential bug in boost::filesystem?
are there any potential boost::filesystem tricks that I've missed that would solve the issue?
One possible workaround would be to re-implement the relative() function to use only path manipulation and does not access the filesystem. But I'd like to avoid the re-implementation.
An small sample program that may exhibit the problem if the tested path has the issue:
#include <vector>
#include <string>
#include <tuple>
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
using namespace std;
using namespace boost::filesystem;
using boost::system::error_code;
int main()
{
vector<string> testpaths = {
"< path to a directory which is to test >",
};
for(auto & line : testpaths)
{
if(line.empty()) continue; // skip empty lines
cout << " path: " << line << " ";
path testpath(line.c_str());
// simplified testing, use parent of parent
path basepath = testpath.parent_path().parent_path();
boost::system::error_code ec;
path relpath = relative(testpath, basepath, ec);
if(ec) cout << " ---> error: " << ec.message();
else cout << " ok, relative: " << relpath.string();
cout << endl;
}
}
I had the same problem where the path only contains a directory using boost 1.65.1:
unexpected exception: boost::filesystem::weakly_canonical: The process cannot access the file because it is being used by another process;
This also only happens on a network drive when the path contains a symbolic link.
It seems that this is a synchronization problem. Obviously using boost:filesystem the same symbolic link can not be accessed in parallel.
I defined a custom function that encapsulates and synchronizes the access to weakly_canonical:
static boost::recursive_mutex sgCanonicalMutex;
boost::filesystem::path CanonicalPath(const boost::filesystem::path inPath)
{
boost::recursive_mutex::scoped_lock lk(sgCanonicalMutex);
return boost::filesystem::weakly_canonical(inPath);
}
After that change the problem did not occur anymore.
There also is a note about the underlying system error code ERROR_SHARING_VIOLATION in the documentation of boost::filesystem::status. See https://www.boost.org/doc/libs/1_70_0/libs/filesystem/doc/reference.html
I think that the root cause is in the boost sources:
boost\libs\filesystem\src\operations.cpp
The function read_symlink contains
handle_wrapper h(
create_file_handle(p.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0));
The third parameter (value 0) is the dwShareMode passed to CreateFileW (see https://learn.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew).
This parameter possibly should be FILE_SHARE_READ. This is still left unchanged in the latest boost 1.70.
I was hitting this problem in a multi-process situation, so the lock solution by #RED SOFT ADAIR would not help. Until the Boost fix is released, I implemented this:
auto full_path = boost::filesystem::path(path_str).lexically_normal();
MY_ASSERT(boost::filesystem::exists(full_path), "Path normalization of '%s' resulted in non-existing path '%s'",
path_str.c_str(), full_path.string().c_str());
This worked out fine through the tests I created to expose this problem. lexically_normal operates on the path string, so it does not care about existence of the path. But it's prone to misinterpretations, when links are involved inside the path.
As of Aug./Sept. 2020 this issue also appeared for RStdio 1.2.5033 and 1.3.1073 - created an issue with RStudio dev on gihtub.
They expect their next boost update to fix this bug (again).
Putting this here although it is an RStudio topic - in case someone runs into this from the RStudio side.

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);

Finding where a process was run from

So i have an issue that i have an application that gets started. Then through a test i need to turn it off and start it again. But it needs t obe done without hard coding.
So is there a way of finding where a process was run from? I can find a list of all processes running but dont know if this is even possible.
EDIT: Its on a windows 7 OS.
QueryFullProcessImageName() will provide the path to the executable image for a process:
#include <windows.h>
#include <iostream>
int main()
{
char exe_path[MAX_PATH];
DWORD exe_path_size = MAX_PATH;
if (QueryFullProcessImageName(GetCurrentProcess(),
0,
exe_path,
&exe_path_size))
{
std::cout << exe_path << "\n";
}
return 0;
}
Easy and portable way would be using argv[0].
It returns the full .exe file path which is all you need
First, what do you mean by "find where the process is run from"? I'm assuming you mean the parent's process id, but it could mean current working directory, ip of remote call, etc...
To find the parent's process id, look into getppid().
Edit: this assumes that you (like any sane programmer) are using a unix-like machine.
Edit #2: You're on Windows, so I have no idea.
Edit #3: Since you're looking for the path to the program you are executing, use argv[0]. The first command line arg to int main(int argc, char* argv[]) is always the path to the binary.

Boost: how to create a thread so that you can control all of its standard output, standard errors?

I create a win32 console app in C++. I use some API (not mine, and I can not modify its sources). It Is written so that it writes some of its info onto console screen not asking... each time I call it (48 times per second) So I want to put it into some thread and limit its output capabilities, but I need to get notified when that thread will try to output some message which is important for me. I have message text in standard string. How to do such thing in C++ using boost?
Here's a crazy idea:
If the lib is using cout/cerr, you could replace the streambuf of these global variables with an implementation of your own. It would, on flush/data, check some thread-local variable to see if the data came from the thread that calls the library, then route it somewhere else (i.e. into a std::string/std::ostringstream) instead of to the regular cout/cerr streambufs. (Which you should keep around.)
If it's using c's stdout/stderr, I think it'd be harder to do properly, but it might be doable still. You'd need to create some pipes and route stuff back and forth. More of a C/unixy question then, which I don't know that much about... yet. :)
Hope it helps.
That feature does not exist in Boost. You can, however, use _dup2 to replace the standard out descriptor:
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <io.h>
#include <iostream>
#include <windows.h>
int main()
{
HANDLE h = CreateFile(TEXT("test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (0 == SetStdHandle(STD_OUTPUT_HANDLE, h)) {
std::fprintf(stderr, "`SetStdHandle` failed with error %d\n", (int)GetLastError());
return EXIT_FAILURE;
}
int h_desc = _open_osfhandle((long)h, 0);
_dup2(h_desc, STDOUT_FILENO);
std::printf("test\r\n"); // This actually writes to `h`.
std::fflush(stdout);
std::cout << "another test" << std::endl; // Also writes to `h`
CloseHandle(h);
return EXIT_SUCCESS;
}
Essentially what this trick does is allow you to redirect all writes to stdout, std::cout, and GetStdHandle(STD_OUTPUT_HANDLE) to a writable handle of your choosing (h). Of course, you can use CreatePipe to create the writable handle (h) and read from the readable end in another thread.
EDIT: If you are looking for a cross-platform solution, note that this trick is even easier on POSIX-compatible systems because dup2 is a standard function in unistd.h and "writable handles" are already descriptors.
I cannot think of a way to achieve in Boost what you want, as the problem is described.
However, this API behaviour is very perplexing. Spitting out reams of output to the console is a bit antisocial. Are you using a Debug build of the API library? Are you sure there's no way to configure the API such that it outputs this data to a different stream, so that you can filter it without capturing the entire standard output? Is there a way to reduce the amount of output, so that you only see the important events you care about?
If you really need to capture standard output and act on certain strings (events) of interest, then Win32 provides ways to do this, but I'd really take a hard look at whether this output can be modified to meet your needs before resorting to that.

Passing information between two seperate programs

I want to pass a value of an input variable in my program lets say#1 to another program #2 and i want #2 to print the data it got to screen, both are needed to be written in c++. The this will be on Linux.
Depending on the platform there are a number of options available. What you are trying to do is typically called inter-process communication (IPC).
Some options include:
Sockets
Pipes
Queues
Shared Memory
What is easiest is probably dependent on the platform youa are using.
As always, there is a Boost library for that (God, I like Boost).
Nic has covered all the 4 that I wanted to mention (on the same machine):
Sockets
Pipes
Queues
Shared Memory
If writing system calls is troublesome for you, you may want to use the following libraries:
Boost http://www.boost.org/
Poco http://pocoproject.org/blog/
Nokia Qt http://qt.nokia.com/
Something you can read from Qt portable IPC: only QSharedMemory?
If effeciency is not prime concern then use normal file i/o.
else go for IPC to do so.
As far as Windows is concern you have following options :
Clipboard ,
COM ,
Data Copy ,
DDE ,
File Mapping ,
Mailslots ,
Pipes ,
RPC ,
Windows Sockets
For Linux , use can use Name Pipes(efficient) or sockets.
If you're on Windows, you can use Microsoft Message Queueing. This is an example of queue mentioned previously.
If the data to be passed is just a variable, then one of the option is to set it as Environment Variable [ Var1 ] by program #1 and access it, in Program #2 [ if both are running on same env/machine ]. Guess this will be the easiest one, instead of making it complex, by using IPC/socket etc.
I think most of the answers have address the common IPC mechanisms. I'd just like to add that I would probably go for sockets because it's fairly most standard across several platforms. I decided to go for that when I needed to implement IPC that worked both on Symbian Series 60 and Windows Mobile.
The paradigm is straightforward and apart from a few platform glitches, the model worked the same for both platforms. I would also suggest using Protocol Buffers to format the data you send through. Google uses this a lot in its infrastructure. http://code.google.com/p/protobuf/
DBUS
QtDbus
DBus-mm
In response to your comment to Roopesh Majeti's answer, here's a very simple example using environment variables:
First program:
// p1.cpp - set the variable
#include <cstdlib>
using namespace std;;
int main() {
_putenv( "MYVAR=foobar" );
system( "p2.exe" );
}
Second program:
// p2.cpp - read the variable
#include <cstdlib>
#include <iostream>
using namespace std;;
int main() {
char * p = getenv( "MYVAR" );
if ( p == 0 ) {
cout << "Not set" << endl;
}
else {
cout << "Value: " << p << endl;
}
}
Note:
there is no standard way of setting an environment variable
you will need to construct the name=value string from the variable contents
For a very dirt and completely nonprofessional solution you can do it like me.
Save the variable in to a file and then read it (in an infinite loop every x time) with the other program.
fsexample.open("F:/etc etc ...");
fsexample >> data1 >> data2; // etc etc
and on the other side
fsexample.open("F:/etc etc ...");
fsexample << data1 << data2; // etc etc
The trick is that F is a virtual drive created with ramdisk so it is fast
and heavy-duty proof.
You could have problem of simultaneous access but you can check it with
if (!fsexample.is_open()) {
fsexample_error = 1;
}
and retry on failure.