How to open Nano and get a string from it in C++? - c++

I am creating a simple logging program. When a user enters log some_file into the console, the program currently simply receives some basic input from cin, and records it into some_file.
However, instead of implementing my own editor with cin, I'd like to open the Nano editor and let the user edit his message there.
Then, when the message is complete, I'd like my C++ logger to receive it as a string and carry on.
This is exactly what git does on commits.
How can I achieve this?
(Preferably without using tools such as expect, just raw C++ code.)

Most editors expect to work with normal files, so you'd typically create a temporary file, then pass the name of that file to the editor on its command line. When the editor returns, you copy the content from the temporary file into your log, then destroy the file.

If you want to use the Nano editor then you need to run the system() function to invoke Nano with a temporary file. Then remove the file later..
std::string filename = "/tmp/.out." + std::to_string(getpid());
std::string cmd = "/bin/nano " + filename
system(cmd.c_str());
// read from filename
unlink(filename.c_str());
Update
If using tmpnam() as suggested by DevSolar
char filename[L_tmpnam];
tmpnam(filename);
std::string cmd = "/bin/nano " + filename
system(cmd.c_str());
unlink(filename);

what about open a file(passing file name to the editor), save and then read it from your program? I've always thought git works the same way.

Related

preferred c++ i/o stream method: fstream or ifstream/ofstream or something else entirely?

I have created a roster program that accepts user input to create/write/delete information into and out of a specified text file. My issue now becomes wanting to create a lasting text file that isn't overwritten every time I re-run the program and am not sure if using fstream or a combination of of/ifstream is better practice, or if there is maybe a third option I missed when checking the reference docs.
Right now I am simply using: std::ofstream outfile("roster.txt"); which works, until I kill and re-run the program to which my text file is now wiped clean.
check out the append flag. it writes to the end of an existing file.
http://www.cplusplus.com/doc/tutorial/files/
example here.
std::ofstream outfile("roster.txt" , ios::app)

How to open file with ofstream so that other users can append/write to same file?

We have a binary which creates a daily CSV report with some file name like Sample_20170523 i.e filename appended with current date but now the issue is when some other runs the binary on the same day then there is error unable to open the file.Code snippet for this issue is as follows:
std::ofstream of;
of.open("FileName_20170523",ios::out);
if(!of)
std::cout<<"Unable to open file..."<<std::endl;
So after checking it seems this problem arises because the file was already created by another user. So just wanted to know is there any mechanism in c++ in which we can give 777 permissions to programmatically created file ?
You can use either chmod() or fchmod() to change the permission of a file.
system() allows to execute system commands.
system("chmod 777 diretory_to_file/name");
gives r+w+x to everyone if it already exits
std::ofstream of;
of.open("FileName_20170523",ios::out);

Will File I/O In Current Working Directory Ever Fail?

On my home Linux laptop, I like to write wrapper programs and GUI helpers for things I use frequently. However, I don't like Bash scripting very much, so I do a lot of stuff in C++. However, a lot of times, this requires me to use the system() function from the cstdlib.
This system() command is awesome, but I wanted a way to call system() and receive the stdout/stderror. The system() command only returns the return code from the command. So, in a Bash script, one can do:
myVar=$(ls -a | grep 'search string')
echo $myVar
and myVar will output whatever the stdout was for the command. So I began writing a wrapper class that will add a pipe-to-file to the end of the command, open the file, read all of the piped stdout, and return it as either one long string or as a vector of strings. The intricacies of the class are not really relevant here (I don't think anyway), but the above example would be done like this:
SystemCommand systemCommand;
systemCommand.setCommand("ls -a | grep \'search string\' ");
systemCommand.execute();
std::cout << systemCommand.outputAsString() << std::endl;
Behind the scenes, when systemCommand.execute() is called, the class ensures that the command will properly pipe all stdout/stderr to a randomly generated filename, in the current working directory. So for example, the above command would end up being
"ls -a | grep 'search string' >> 1452-24566.txt 2>&1".
The class then goes attempts to open and read from that file, using ifstream:
std::ifstream readFromFile;
readFromFile.open(_outputFilename);
if (readFromFile.is_open()) {
//Read all contents of file into class member vector
...
readFromFile.close();
//Remove temporary file
...
} else {
//Handle read failure
}
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory? If so, what would be a way to make it more robust (specifically on Linux)?
A side/secondary question: Is there a very simplified way to achieve what I'm trying to achieve without using file pipes? Perhaps some stuff available in unistd.h? Thanks for your time.
So here is my main question will std::ifstream ever fail to open a recently created file in the current working directory?
Yes.
Mount a USB thumb drive (or some other removable media)
cd to the mount
Execute your program. While it's executing, remove the drive.
Watch the IO error happen.
There's a ton of other reasons too. Filesystem corruption, hitting the file descriptor limit, etc.
If so, what would be a way to make it more robust (specifically on Linux)?
Make temporary files in /tmp, whose entire purpose is for temporary files. Or don't create a file at all, and use pipes for communication instead (Like what popen does, like harmic suggested). Even so, there are no guarantees; try to gracefully handle errors.

how can I run a .exe file through C++?

My .exe application needs to be opened in console window. Then I have to type the name of a .txt in the console application for it to read. How can I perform all these within my code at once?
I used to be able to run it (and not making it to read .txt) with system("name.exe"), but suddenly it gives,
error: input "name.exe" is not a valid windows application
You can make your application read the filename as a command-line parameter, then you can run your application using system("name.exe name.txt").
In Windows use the CreateProcess API to do this - http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx.
Do not use system.
1- type "name.txt" 2- press enter 3- type name2.exe 4- Press enter. How can I do that through my c++ code?
std::string appName, fileName
std::cin >> appName >> fileName;
system(std::string(appName + " " + filename).c_str())
If names contain spaces, you might need to use getline to read them instead of >>.
--EDIT--
Basically I want once my application is called the input is also automatically given to it.
Creating Child process with redirected input (msdn)
_popen documentation(msdn)
pipe to subprocess (GNU)

Creating, opening and printing a word file from C++

I have three related questions.
I want to create a word file with a name from C++. I want to be able to sent the printing command to this file, so that the file is being printed without the user having to open the document and do it manually and I want to be able to open the document. Opening the document should just open word which then opens the file.
You can use Office Automation for this task. You can find answers to frequently asked questions about Office Automation with C++ at http://support.microsoft.com/kb/196776 and http://support.microsoft.com/kb/238972 .
Keep in mind that to do Office Automation with C++, you need to understand how to use COM.
Here are some examples of how to perform various tasks in word usign C++:
http://support.microsoft.com/kb/220911/en-us
http://support.microsoft.com/kb/238393/en-us
http://support.microsoft.com/kb/238611/en-us
Most of these samples show how to do it using MFC, but the concepts of using COM to manipulate Word are the same, even if you use ATL or COM directly.
As posted as an answer to a similar question, I advise you to look at this page where the author explains what solution he took to generate Word documents on a server, without MsWord being available, without automation or thirdparty libraries.
When you have the file and just want to print it, then look at this entry at Raymond Chen's blog. You can use the verb "print" for printing.
See the shellexecute msdn entry for details.
You can use automation to open MS Word (in background or foreground) and then send the needed commands.
A good starting place is the knowledge base article Office Automation Using Visual C++
Some C source code is available in How To Use Visual C++ to Access DocumentProperties with Automation (the title says C++, but it is plain C)
I have no experience from integrating with Microsoft Office, but I guess there are some APIs around that you can use for this.
However, if what you want to accomplish is a rudimentary way of printing formatted output and exporting it to a file that can be handled in Word, you might want to look into the RTF format. The format is quite simple to learn, and is supported by the RtfTextBox (or is it RichTextBox?), which also has some printing capabilities. The rtf format is the same format as is used by Windows Wordpad (write.exe).
This also has the benefit of not depending on MS Office in order to work.
My solution to this is to use the following command:
start /min winword <filename> /q /n /f /mFilePrint /mFileExit
This allows the user to specify a printer, no. of copies, etc.
Replace <filename> with the filename. It must be enclosed in double-quotation marks if it contains spaces. (e.g. file.rtf, "A File.docx")
It can be placed within a system call as in:
system("start /min winword <filename> /q /n /f /mFilePrint /mFileExit");
Here is a C++ header file with functions that handle this so you don't have to remember all of the switches if you use it frequently:
/*winword.h
*Includes functions to print Word files more easily
*/
#ifndef WINWORD_H_
#define WINWORD_H_
#include <string.h>
#include <stdlib.h>
//Opens Word minimized, shows the user a dialog box to allow them to
//select the printer, number of copies, etc., and then closes Word
void wordprint(char* filename){
char* command = new char[64 + strlen(filename)];
strcpy(command, "start /min winword \"");
strcat(command, filename);
strcat(command, "\" /q /n /f /mFilePrint /mFileExit");
system(command);
delete command;
}
//Opens the document in Word
void wordopen(char* filename){
char* command = new char[64 + strlen(filename)];
strcpy(command, "start /max winword \"");
strcat(command, filename);
strcat(command, "\" /q /n");
system(command);
delete command;
}
//Opens a copy of the document in Word so the user can save a copy
//without seeing or modifying the original
void wordduplicate(char* filename){
char* command = new char[64 + strlen(filename)];
strcpy(command, "start /max winword \"");
strcat(command, filename);
strcat(command, "\" /q /n /f");
system(command);
delete command;
}
#endif