How to build your own CMD using C++? - c++

Recently I want to enhance CMD in Win10 by myself using C++. I don't want to change the original framework of it but to translate the command. At first i wrote something like this:
#include <unistd.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string initial = "retr0# ";
string s;
while(1)
{
cout << initial;
getline(cin,s);
if(s!="exit")
{
system(s.c_str());
cout << "------" << endl;
}
else break;
}
system("pause");
return 0;
}
But I found that if you entered command like "E:" or something else to change the directory, it is impossible for the new thread to inherit the context. My question is, how to solve the problem like this?

In most operating systems (including 1970 era Unix), the working directory is specific to each process.
The system function will run another process. So even if you change its working directory, it only affects the process started by system, not the process running your program.
So you need to define a syntax (perhaps the same cd as Windows CMD has) and parse and implement that command in your own program. You could use SetCurrentDirectory or _chdir

Related

C++ Run a shell command on the same shell instance

So as the title says, I would like to run a shell command on the same shell process/instance in C++ and communicate with it, how can I do that?
I have looked up every corner and I couldn't find an appropriate/straight to the point answer.
I am not a C++ overlord, my answer could be dumb.
Now I could use a combination of fork/exec on unix, but I'm on windows.
If there is a cross platform solution, please mention it below.
Thanks in advance.
Pseudocode:
SHELL shell = make_shell();
shell.run("cd desktop");
shell.run("dir");
print(shell.stdout)
The standard library in C++ does not provide a way to do what you want. However, you can use a third party library, like boost::process, which will make the communication part between your program and the sub-processes pretty portable. If you want to execute built-in shell commands, or commands using the shell, you will still need to deal with differences in the shells used on the different platforms.
The boost::process library contains a lot of different ways of creating and communicating with sub processes (reference), both synchronously and asynchronously, so browse through the reference page to get a feeling for what it can do.
Here's a simple example that uses boost::process::system to run the command dir in the directory desktop and collects the output from that command. It does not use the shell (which should generally be avoided) but uses boost::process::search_path to find the command (in your PATH) and executes the command directly without involving a shell:
#include <boost/process.hpp>
#include <boost/process/start_dir.hpp>
#include <iostream>
#include <string>
int main() {
namespace bp = ::boost::process;
bp::ipstream out;
bp::ipstream err;
bp::system(bp::search_path("dir"),
bp::start_dir = "./desktop",
bp::std_out > out, // collect stdout in out
bp::std_err > err, // collect stderr in err
bp::std_in < stdin); // for commands reading from stdin
// display what was collected on stdout and stderr:
std::string line;
std::cout << "stdout capture:\n";
while(std::getline(out, line)) {
std::cout << '[' << line << "]\n";
}
std::cout << "\nstderr capture:\n";
while(std::getline(err, line)) {
std::cout << '[' << line << "]\n";
}
}
Note: You need to link with boost_filesystem and boost_atomic for this example to work.
Linux: exec
Windows: CreateProcessA
write ifdefs to switch based upon platform.
I found this answer: https://stackoverflow.com/a/57096619/9282847.
It seems to be the only method which is both standard, and portable (assuming the implementation supports std::filesystem).
Like:
#include <filesystem>
#include <iostream>
int main() {
namespace fs = std::filesystem;
const auto kDesktopPath = fs::path("~/Desktop"); // portable filepath
fs::current_path(kDesktopPath); // set CWD (This will throw on compiler explorer)
auto dir_it = fs::recursive_directory_iterator{ fs::current_path() };
for (auto& f: dir_it) {
std::cout.put('\n') << f;
}
}
Live example on compiler explorer

How to use file strings as commands in c++

I am trying to make a program on Windows 10 using Visual Studio 2015 that would sim-link certain files to certain locations. I am trying to make a text file with the location of the files, and the sim-link destination to use.
This is an example of the file data that would be in the properties.txt file:
FileLocation: "Z:\Folder\file.txt"
FileMkdirLocation: "Z:\Folder2\file.txt"
I want to use something like system(mkdir "sim-link_file_location" "file_location") by changing the data that is in properties.txt. I want to be able to add more than 1 file, without recompiling the program and writing each command for each file, one by one.
The problem is that I don't know how to make the commands use the data in the file.
EDIT: I managed to find out a way, but I get errors when compiling the program. I use this code:
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdlib.h>
using namespace std;
//initialization of Properties File used
ifstream PropertiesFile ("PropertiesFile.txt");
int main()
{
//initialization of variables used
int input_option;
char FileLocation[256], Command[]="mklink ";
// string FileLocation, Command;
PropertiesFile >> FileLocation;
/* switch (input_option)
{
case "add all mods":
}
*/
cout << "FileLocation: " << FileLocation;
cout << endl;
strcat(Command, FileLocation);
Command[strlen(FileLocation)] = '\0';
cout << Command;
cout << endl;
//system(command);
system("pause");
return 0;
}
I know that i haven't used all variables yet.
It tells me that "strcat" is deprecated and to use "strcat_s" instead, and when i replace it with that, I get
"Debug Assertion Failed - Expression: (L"Buffer is too small" && 0)"
I had to make the "Command" char bigger than "FileLocation" because then strcat_s would not be able to copy the content. After that the program worked fine, and there were no other Assert Errors.
The command to create a soft link in linux is: ln -s <source> <destination>
You can use this in a system(""); call, BUT before you continue in your code, you will have to make sure that the kernel finished executing this command.
After that you can read the link as if it was the original file.

Launching a Script from C++

What I want to do is create a program to prompt the user for input. If they select yes I want to terminate the rest of the program. If they select no I want to immediately run a script. If there is no input for 5 minutes I want the script to automatically run. The only reason I want to use the script or batch file is I previously created it and it is already done.
The problems I am having is I am not sure how to declare the file system and file so it can be called. Then, I am not sure how to call the script to run. I am also not sure how to count down the 5 minutes to auto launch the script when ready. Below is my file in all it's current form.
//Program Name Apex Database Backup
//Written 8/3/2016
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <windows.h>
#include <stdio.h>
using namespace std;
int main()
{
//Declarations
bool yes;
bool no;
char yesOrno;
string open;
FILE *C$;
//Prompt the User for Input
cout << "Are You Currently Loading Out? If Not This Program Will Execute in 5 Minutes. " << endl;
cout << "You Will Lose Your Connection to Apex! " << endl;
cout << "Enter yes or no: " << endl;
//Get User Input
cin >> yesOrno;
//Open the File
public FILE *DatabaseBackup.bat fopen(*C$)
//Process the Selection
if (no)
{
ShellExecute (DatabaseBackup.bat);
}
return 0;
}
The problems I am having is I am not sure how to declare the file system and file so it can be called.
I'm not sure what you mean by "declare the file system". If you want to open a file, take a look at C++ File IO
Then, I am not sure how to call the script to run
Running the script is a OS related function. See this answer on how to do this.
I am also not sure how to count down the 5 minutes to auto launch the script when ready.
You need to use a timer/clock with a signal/interrupt.

C++ getenv doesnt update

I'm trying to make a program that a bash script runs. I want the bash script to be able to change the state of the c++ program, and the only thing I could find was to use environment variables. Thing is, its seems getenv only gets the value at the time when the program was run.
Bash
export BLINK=1
./blink &
sleep 5s
unset BLINK
C++
int main(int args, char **argv) {
char *blink = getenv("BLINK");
while(blink && blink[0] == '1')
{
std::cout << getenv("BLINK") << std::endl;
usleep(500000);
}
return 1;
}
So what this does is run the blink program, wait 5 seconds then unset the environment. The C++ program however always sees the enviorment value as 1 and never stops. How do I get an updated environment variable while the program is running? Or is there a better way to have a bash script control the state of a c++ program.
EDIT I should note, I do not want to just kill the process either because it has to turn off hardware when it ends.
It is not possible to modify program environment after it is started. You have to use another method of interprocess communication. The simplest one is to register handler for some signal to your app (e.g. SIGUSR1), and then send it using kill -SIGUSR1 <pid> command.
There are also other solutions available, e.g. create named pipe (using pipe shell command), and check periodically if someone wrote something to it. If yes, exit loop.
You can also use sockets if you want, but this could be more complicated.
The C++ programs environment is not changing when you change it in bash - since when you start your program it gets a copy of the parent's environment and has no access to the parent process's environment.
You can use a file to easily share data, however.
Bash
echo "1" > blink.txt
./blink &
sleep 5s
echo "0" > blink.txt
C++
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <unistd.h>
using namespace std;
string getfile(const string& filename) {
ifstream in(filename.c_str(), ios_base::binary);
in.exceptions(ios_base::badbit | ios_base::failbit | ios_base::eofbit);
return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
}
int main(int argc, char* argv[]) {
string blink = getfile("blink.txt");
while(blink[0] == '1')
{
std::cout << getfile("blink.txt") << std::endl;
usleep(500000);
}
return 1;
}

Is there a decent wait function in C++?

One of the first things I learned in C++ was that
#include <iostream>
int main()
{
std::cout<<"Hello, World!\n";
return 0;
}
would simply appear and disappear extremely quickly without pause. To prevent this, I had to go to notepad, and save
helloworld.exe
pause
ase
helloworld.bat
This got tedious when I needed to create a bunch of small test programs, and eventually I simply put while(true); at the end on most of my test programs, just so I could see the results. Is there a better wait function I can use?
you can require the user to hit enter before closing the program... something like this works.
#include <iostream>
int main()
{
std::cout << "Hello, World\n";
std::cin.ignore();
return 0;
}
The cin reads in user input, and the .ignore() function of cin tells the program to just ignore the input. The program will continue once the user hits enter.
Link
Please note that the code above was tested on Code::Blocks 12.11 and Visual Studio 2012
on Windows 7.
For forcing your programme stop or wait, you have several options :
sleep(unsigned int)
The value has to be a positive integer in millisecond.
That means that if you want your programme wait for 2 seconds, enter 2000.
Here's an example :
#include <iostream> //for using cout
#include <stdlib.h> //for using the function sleep
using namespace std; //for using cout
int main(void)
{
cout << "test" << endl;
sleep(5000); //make the programme waiting for 5 seconds
cout << "test" << endl;
sleep(2000); // wait for 2 seconds before closing
return 0;
}
If you wait too long, that probably means the parameter is in seconds. So change it to this:
sleep(5);
For those who get error message or problem using sleep try to replace it by _sleep or Sleep especially on Code::Bloks.
And if you still getting problems, try to add of one this library on the beginning of the code.
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <dos.h>
#include <windows.h>
system("PAUSE")
A simple "Hello world" programme on windows console application would probably close before you can see anything. That the case where you can use system("Pause").
#include <iostream>
using namespace std;
int main(void)
{
cout << "Hello world!" << endl;
system("PAUSE");
return 0;
}
If you get the message "error: 'system' was not declared in this scope" just add
the following line at the biggining of the code :
#include <cstdlib>
cin.ignore()
The same result can be reached by using cin.ignore() :
#include <iostream>
using namespace std;
int main(void)
{
cout << "Hello world!" << endl;
cin.ignore();
return 0;
}
cin.get()
example :
#include <iostream>
using namespace std;
int main(void)
{
cout << "Hello world!" << endl;
cin.get();
return 0;
}
getch()
Just don't forget to add the library conio.h :
#include <iostream>
#include <conio.h> //for using the function getch()
using namespace std;
int main(void)
{
cout << "Hello world!" << endl;
getch();
return 0;
}
You can have message telling you to use _getch() insted of getch
Lots of people have suggested POSIX sleep, Windows Sleep, Windows system("pause"), C++ cin.get()… there's even a DOS getch() in there, from roughly the late 1920s.
Please don't do any of these.
None of these solutions would pass code review in my team. That means, if you submitted this code for inclusion in our products, your commit would be blocked and you would be told to go and find another solution. (One might argue that things aren't so serious when you're just a hobbyist playing around, but I propose that developing good habits in your pet projects is what will make you a valued professional in a business organisation, and keep you hired.)
Keeping the console window open so you can read the output of your program is not the responsibility of your program! When you add a wait/sleep/block to the end of your program, you are violating the single responsibility principle, creating a massive abstraction leak, and obliterating the re-usability/chainability of your program. It no longer takes input and gives output — it blocks for transient usage reasons. This is very non-good.
Instead, you should configure your environment to keep the prompt open after your program has finished its work. Your Batch script wrapper is a good approach! I can see how it would be annoying to have to keep manually updating, and you can't invoke it from your IDE. You could make the script take the path to the program to execute as a parameter, and configure your IDE to invoke it instead of your program directly.
An interim, quick-start approach would be to change your IDE's run command from cmd.exe <myprogram> or <myprogram>, to cmd.exe /K <myprogram>. The /K switch to cmd.exe makes the prompt stay open after the program at the given path has terminated. This is going to be slightly more annoying than your Batch script solution, because now you have to type exit or click on the red 'X' when you're done reading your program's output, rather than just smacking the space bar.
I assume usage of an IDE, because otherwise you're already invoking from a command prompt, and this would not be a problem in the first place. Furthermore, I assume the use of Windows (based on detail given in the question), but this answer applies to any platform… which is, incidentally, half the point.
The appearance and disappearance of a window for displaying text is a feature of how you are running the program, not of C++.
Run in a persistent command line environment, or include windowing support in your program, or use sleep or wait on input as shown in other answers.
the equivalent to the batch program would be
#include<iostream>
int main()
{
std::cout<<"Hello, World!\n";
std::cin.get();
return 0;
}
The additional line does exactly what PAUSE does, waits for a single character input
There is a C++11 way of doing it. It is quite simple, and I believe it is portable. Of course, as Lightness Races in Orbit pointed out, you should not do this in order to be able to see an Hello World in your terminal, but there exist some good reason to use a wait function. Without further ado,
#include <chrono> // std::chrono::microseconds
#include <thread> // std::this_thread::sleep_for
std::this_thread::sleep_for(std::chrono::microseconds{});
More details are available here. See also sleep_until.
Actually, contrary to the other answers, I believe that OP's solution is the one that is most elegant.
Here's what you gain by using an external .bat wrapper:
The application obviously waits for user input, so it already does what you want.
You don't clutter the code with awkward calls. Who should wait? main()?
You don't need to deal with cross platform issues - see how many people suggested system("pause") here.
Without this, to test your executable in automatic way in black box testing model, you need to simulate the enter keypress (unless you do things mentioned in the footnote).
Perhaps most importantly - should any user want to run your application through terminal (cmd.exe on Windows platform), they don't want to wait, since they'll see the output anyway. With the .bat wrapper technique, they can decide whether to run the .bat (or .sh) wrapper, or run the executable directly.
Focusing on the last two points - with any other technique, I'd expect the program to offer at least --no-wait switch so that I, as the user, can use the application with all sort of operations such as piping the output, chaining it with other programs etc. These are part of normal CLI workflow, and adding waiting at the end when you're already inside a terminal just gets in the way and destroys user experience.
For these reasons, IMO .bat solution is the nicest here.
What you have can be written easier.
Instead of:
#include<iostream>
int main()
{
std::cout<<"Hello, World!\n";
return 0;
}
write
#include<iostream>
int main()
{
std::cout<<"Hello, World!\n";
system("PAUSE");
return 0;
}
The system function executes anything you give it as if it was written in the command prompt. It suspends execution of your program while the command is executing so you can do anything with it, you can even compile programs from your cpp program.
Syntax:
void sleep(unsigned seconds);
sleep() suspends execution for an interval (seconds).
With a call to sleep, the current program is suspended from execution for the number of seconds specified by the argument seconds. The interval is accurate only to the nearest hundredth of a second or to the accuracy of the operating system clock, whichever is less accurate.
This example should make it clear:
#include <dos.h>
#include <stdio.h>
#include <conio.h>
int main()
{
printf("Message 1\n");
sleep(2); //Parameter in sleep is in seconds
printf("Message 2 a two seconds after Message 1");
return 0;
}
Remember you have to #include dos.h
EDIT:
You could also use winAPI.
VOID WINAPI Sleep(
DWORD dwMilliseconds
);
Sleep Function(Windows)
Just a note,the parameter in the function provided by winapi is in milliseconds ,so the sleep line at the code snippet above would look like this "Sleep(2000);"
getchar() provides a simplistic answer (waits for keyboard input).
Call Sleep(milliseconds) to sleep before exit.
Sleep function (MSDN)
You can use sleep() or usleep().
// Wait 5 seconds
sleep( 5 );
Well, this is an old post but I will just contribute to the question -- someone may find it useful later:
adding 'cin.get();' function just before the return of the main() seems to always stop the program from exiting before printing the results: see sample code below:
int main(){
string fname, lname;
//ask user to enter name first and last name
cout << "Please enter your first name: ";
cin >> fname;
cout << "Please enter your last name: ";
cin >> lname;
cout << "\n\n\n\nyour first name is: " << fname << "\nyour last name is: "
<< lname <<endl;
//stop program from exiting before printing results on the screen
cin.get();
return 0;
}
Before the return statement in you main, insert this code:
system("pause");
This will hold the console until you hit a key.
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s;
cout << "Please enter your first name followed by a newline\n";
cin >> s;
cout << "Hello, " << s << '\n';
system("pause");
return 0; // this return statement isn't necessary
}
The second thing to learn (one would argue that this should be the first) is the command line interface of your OS and compiler/linker flags and switches.