Change default file descriptor for Rust print functions - rust

I'm working on Rust and using a shared library written in C++. The problem that the C++ library spawns a few threads that constantly print to stdout (1) and that interferes with my own logging.
I was able to duplicate stdout using dup to fd = 3. Then I open up a pipe (4, 5), and use dup2 to
move old stdout to one end of the pipe.
As a result:
C++ library writes to fd = 1 (old stdout), but that goes to another pipe where I can capture the data in another thread (say I read from fd = 5). Then I can parse those logs and print them to the console.
In Rust code I can use libc::write to fd = 3 and that will go directly to the console.
The problem now is that standard Rust function such as println! will still try to write to fd = 1, but I'd like to be able to change the default behavior so Rust code will write to fd = 3 instead of 1, that way, any Rust print related function will print to the console, and everything from the shared library will be parsed on a separate thread.
Is that possible to do in stable Rust? Closest thing I found is set_print function which looks like it's unstable and I couldn't even use it using +nightly build.

If it's acceptable to use writeln! instead of println!, you can call from_raw_fd to open a proper File:
use std::fs::File;
use std::io::{BufWriter, Write};
use std::os::unix::io::FromRawFd;
let mut out = BufWriter::new(unsafe { File::from_raw_fd(3) });
writeln!(out, "hello world!")?;
// ...
Note: from_raw_fd is unsafe because you must ensure that the File assumes sole ownership of the file descriptor, in this case that no one else closes or interacts with file descriptor 3. (But you can use into_raw_fd to re-assert ownership of the fd it while consuming the File.)

Related

Saving a binary as a rust variable

I would like to have a rust program compiled, and afterwards have that compiled binary file's contents saved in another rust program as a variable, so that it can write that to a file. So for example, if I have an executable file which prints hello world, I would like to copy it as a variable to my second rust program, and for it to write that to a file. Basically an executable which creates an executable. I dont know if such thing is possible, but if it is I would like to know how it's done.
Rust provides macros for loading files as static variables at compile time. You might have to make sure they get compiled in the correct order, but it should work for your use case.
// The compiler will read the file put its contents in the text section of the
// resulting binary (assuming it doesn't get optimized out)
let file_contents: &'static [u8; _] = include_bytes!("../../target/release/foo.exe");
// There is also a version that loads the file as a string, but you likely don't want this version
let string_file_contents: &'static str = include_str!("data.txt");
So you can put this together to create a function for it.
use std::io::{self, Write};
use std::fs::File;
use std::path::Path;
/// Save the foo executable to a given file path.
pub fn save_foo<P: AsRef<Path>>(path: P) -> io::Result<()> {
let mut file = File::create(path.as_ref().join("foo.exe"))?;
file.write_all(include_bytes!("foo.exe"))
}
References:
https://doc.rust-lang.org/std/macro.include_bytes.html
https://doc.rust-lang.org/std/macro.include_str.html

Writing a raw binary structure to file in D?

I'm trying to have a binary file which contains several binary records defined in some struct. However, I do cannot seem to find how to do it. Looking at other examples, I've managed to write strings without problems, but not struct. I just want to write it like I would in C with fwrite(3), but in D version 2.
Here is what I've tried so far:
using stream.write(tr) - writes human readable/debug representation
using stream.rawWrite(tr) - this sounded like what I need, but fails to compile with:
Error: template std.stdio.File.rawWrite cannot deduce function from
argument types !()(TitleRecord), candidates are:
/usr/lib/ldc/x86_64-linux-gnu/include/d/std/stdio.d(1132): std.stdio.File.rawWrite(T)(in T[] buffer)
trying rawWrite as above, but casting data to various things, also never compiles.
even trying to get back to C with fwrite, but can't get deep enough to get file descriptor I need.
Reading the docs has not been very helpful (writing strings works for me too, but not writing struct). I'm sure there must be simple way to do it, but I'm not able to find it.... Other SO questions did not help me. I D 1.0, it might have been accomplished with stream.writeExact(&tr, tr.sizeof) but that is no longer an option.
import std.stdio;
struct TitleRecord {
short id;
char[49] text;
};
TitleRecord tr;
void main()
{
auto stream = File("filename.dat","wb+");
tr.id = 1234;
tr.text = "hello world";
writeln(tr);
//stream.write(tr);
//stream.rawWrite(tr);
//stream.rawWrite(cast(ubyte[52]) tr);
//stream.rawWrite(cast(ubyte[]) tr);
//fwrite(&tr, 4, 1, stream);
}
For this that error is saying it expects an array not a struct. So one easy way to do it is to simply slice a pointer and give that to rawWrite:
stream.rawWrite((&tr)[0 .. 1]);
The (&tr) gets the address, thus converting your struct to a pointer. Then the [0 .. 1] means get a slice of it from the beginning, grabbing just one element.
Thus you now have a T[] that rawWrite can handle containing your one element.
Be warned if you use the #safe annotation this will not pass, you'd have to mark it #trusted. Also of course any references inside your struct (including string) will be written as binary pointers instead of data as you surely know from C experience. But in the case you showed there you're fine.
edit: BTW you could also just use fwrite if you like, copy/pasting the same code over from C (except it is foo.sizeof instead of sizeof foo). The D File thing is just a small wrapper around C's FILE* and you can get the original FILE* back out to pass to the other functions with stream.getFP() http://dpldocs.info/experimental-docs/std.stdio.File.getFP.html )
rawWrite expects an array, but there are many workarounds.
One is to create a single element array.
file.rawWrite([myStruct]);
Another one is casting the struct into an array. My library called bitleveld has a function for that called reinterpretAsArray. This also makes it easy to create checksums of said structs.
Once in a while I've encountered issues with alignment using this method, so be careful. Could be fixed by changing the align property of the struct.

Can I read from stdin in a non-canonical way?

Is there any way one could read from stdin in non-canonical mode under Linux? Non-canonical input means that calls to read() on stdin shall return as soon as the user types, which is not the default behaviour, as one can see by trying:
// Create a buffer
let mut buffer :[u8; 1] = [0];
// Loops over the input from stdin, one character a time
while io::stdin().read(&mut buffer).unwrap() > 0 {
println!("{:?}", buffer);
}
This code waits for the user to press return to print the contents of buffer. The desired behaviour would be for it to print as the user typed. In the documentation for Stdin (the struct returned by the stdin() call in the code above), there is no reference to how one could change this default behaviour.
No, not without external crates or unsafe FFI code. You will probably want to use the termios functions. Specifically, see ICANON and tcsetattr. The crate nix has bindings for these functions. See here for an example of how to use them in Rust.

In OCaml, how can I create an out_channel which writes to a string/buffer instead of a file on disk

I have a function of type in_channel -> out_channel -> unit which will output something to an out_channel. Now I'd like to get its output as a string. Creating temporary files to write and read it back seems ugly, so how can I do that? Is there any other methods to create out_channel besides Pervasives.open_out family?
Actually, this function implemented a repl. What I really need is to test it programmatically, so I'd like to first wrap it to a function of type string -> string. For creating the in_channel, it seems I can use Scanf.Scanning.from_string, but I don't know how to create the out_channel parameter.
OCaml Batteries Included has output_string and output_buffer functions in its BatIO module which seem to do what you want: http://ocaml-batteries-team.github.com/batteries-included/hdoc/BatIO.html
It might require you to use their input/output types.
If you don't mind your tests relying on the Unix module, then you can use Unix.pipe to create a file descriptor pair, create an in_channel from the readable side, an out_channel from the writable side, and then write the string to the writable side and pass the in_channel to the code under test.
val pipe : unit -> file_descr * file_descr
Create a pipe. The first component of the result is opened for
reading, that's the exit to the pipe. The second component is
opened for writing, that's the entrance to the pipe.
val in_channel_of_descr : file_descr -> Pervasives.in_channel
Create an input channel reading from the given descriptor. The
channel is initially in binary mode; use set_binary_mode_in ic
false if text mode is desired.
val out_channel_of_descr : file_descr -> Pervasives.out_channel
Create an output channel writing on the given descriptor. The
channel is initially in binary mode; use set_binary_mode_out oc
false if text mode is desired.
Unix pipes are a bit heavy-weight for anything with high throughput, but they should be fine for a test-harness.

gdb watchpoint on struct variables

I have a structure like this :
struct A
{
int a;
char b;
};
this structure is referenced at various places in a large code. The pointer to this struct is passed on to different functions and accordingly the variables in this structure are updated. i want to set a watchpoint on variable a in this struct as it travels across many functions. to see how a changes. How do I set this watch point ?
First set a breakpoint where you create an instance of your struct using break, like
break myfile.c:9
Then just use watch to set a watchpoint, like
watch myStructInstance.a
for variable a or
watch *0x7ffff75177f0
for a memory address. The memory address can be obtained easily by using print, like
print &myStructInstance.a
Now every time variable a or the given memory address gets modified gdb will break.
I come with the same problem when debugging my virtual memory simulator. The problem is how to keep a close look at the data inside structs.
I tried using print to check, but that's too noisy. Because I have to print out more than 15 variables.
I also tried using watchpoint, but on my machine, I can only set no more than 4 hardware watchpoints. That's not even close to my goal.
Finally, I find my solution by using user-defined function in .gdbinit file. e.g. if I want to watch array of my structure, using
define lookintoStructs
if mystruct != 0x0
print mystruct[0]
print mystruct[1]
print mystruct[2]
print mystruct[3]
print mystruct[4]
print mystruct[5]
end
end
to make it more convenient to use, I'd like to make it hook to my next instruction in gdb.
define hook-next
lookintoStructs
end
so when I call next or n in gdb, lookintoStructs could be called automatically. works fine for me.

Resources