As the title mentions, I am trying to open Microsoft Word through this program and am running into a little bit of difficulty. Having done some research into processes, I decided to go through the route of working with Process ID's and the Fork function to handle opening another file within my program. The area where I seem to be running into some difficulty are with the exec family functions. Their seems to be a variety of different uses for these functions, but I am having a difficult time wrapping my head around which function I should use and whether I am syntatically laying out my arguments correctly.
My console prints the following out to the screen when I type "msword":
Hello ---, what application would you like to open?
msword
Creating Child Process To Open Microsoft Word
parent process
Opening Microsoft Word
#include <stdio.h>
#include <iostream>
#include <string>
// Routine Headers
#include <sys/types.h>
#include <unistd.h>
using namespace std;
//function that actually processes loading the program, will take the result of searchApplication
void loadApplication(string path)
{
// If the user typs Microsoft Word (msword abbreviation...)
if(path == "msword")
{
cout << "Creating Child Process To Open Microsoft Word\n";
pid_t ProcessID = fork();
if(ProcessID == -1)
{
cout << "Error creating another Process... Exiting\n";
exit(1);
}
// This is the child process
else if (ProcessID == 0)
{
execle("/Applications/Microsoft Office 2011", nullptr);
}
// This is the parent process
else
{
cout << "parent process\n";
}
}
int main()
{
cout << "Hello ---, what application would you like to open?\n";
string input;
cin >> input;
loadApplication(input);
return 0;
}
You don't have to use fork/exec for this. Just pass the open command to system():
#include <cstdlib>
int main() {
system("open /Applications/App\\ Store.app");
return 0;
}
Note that you will need to escape any spaces in the application name (as shown above), and specify the full name (not just the displayed name).
Here's a very closely related question.
Related
I am trying to implement a custom shell in linux and I am stuck on pipes implementaion by which output of a command would become input of other.
From what I have read on a website, stdin and stdout are separate for different processes.
-> Following that approach I have redirected output stdout of child process to writing end of pipe and after that I have executed ls command.
-> In the parent process, I have redirected its stdin to reading end of pipe and after that sort command has been executed(assuming it will
take input from pipe)
But the code attached below is not giving any output.
Kindly tell whats the reason.
Do I need to fork more children but why?
What if the command is ls|sort|grep "q1" ?
How would I handle if there are multiple pipes?
I have attached the code as well
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <cstring>
#include<sys/wait.h>
#include <sys/types.h>
#pragma warning(disable : 4996)
using namespace std;
int main()
{
int fd[2];
pipe(fd);
pid_t p1;
p1=fork();
int temp;
if(p1==0) //child
{
cout << "CHILD " << endl;
dup2(fd[1],STDOUT_FILENO); //ouput directed to writing end of pipe
close (fd[1]);
close(fd[0]);
execlp("/bin/ls", "/ls" ,NULL);
}
else
{
wait(NULL);
cout << "Parent" << endl;
dup2(fd[0],STDIN_FILENO); //input directed to reading end
close(fd[0]);
close (fd[1]);
execlp("/bin/sort","/sort",NULL);
cout <<"NOT CORRECT" << endl;
}
return 0;
}
In the if block for child process, you can remove this line:
close (fd[1]);
You are going to write to the pipe at it's write end in the child process, so why would you want to close that end?
Similarly, you should remove this line in the else block for parent process:
close(fd[0]);
Again, you will be needing read end of the pipe for reading in the parent process, so it should stay open.
As for multiple pipes, I am not sure how to fix that part.
I'm programming a tool in C++ to remove the 000.exe malware. The malware creates a lot of files on the desktop named "UR NEXT UR NEXT UR NEXT" etc. My first step is to remove all these files from the desktop. What can I do to check every file on the desktop and for each one that contains the string "UR NEXT" somewhere in the file name, delete it. I have a basic structure of my program already written but I'm really stuck figuring out the user's username folder, then deleting ever file containing "UR NEXT" on the desktop. Any help would be greatly appreciated. I'm using Visual Studio 2019 and I already have an elevation added to the program.
#include <iostream>
#include <Windows.h>
#include <WinUser.h>
using namespace std;
int main()
{
string answer;
cout << "=~=~=~=~=~=~=~=~=~=~=~=~=~=\n000.exe Removal Tool\n\nby OrcaTech\n\nThis tool can be used to remove the 000.exe malware from your Windows PC. Type \"y\" below and press [ENTER] to begin the removal process.\n=~=~=~=~=~=~=~=~=~=~=~=~=~=" << endl;
cin >> answer;
if (answer == "y")
{
cout << "Starting Removal Process..." << endl;
cout << "Your computer will restart multiple times." << endl;
//Stop "run away" spam message boxes
system("taskkill /f /im runaway.exe");
//Change the wallpaper back to the default.
const wchar_t* path = L"%SystemRoot%\\Web\\Wallpaper\\Windows\\img0.jpg";
SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (void*)path, SPIF_UPDATEINIFILE);
/* code to delete all files on desktop containing UR NEXT goes here */
system("pause");
return 0;
} else {
exit(0);
}
}
You can use std::filesystem::directory_iterator to iterate over every file in the desktop folder and remove the files with specific names:
#include <filesystem>
#include <string>
#include <vector>
int main()
{
std::vector<std::filesystem::path> filesToRemove;
for (const auto& i : std::filesystem::directory_iterator("path_to_desktop"))
{
std::string fileName = i.path().filename().string();
if (fileName.find("UR NEXT") != std::string::npos)
{
filesToRemove.emplace_back(i);
}
}
for (const auto& i : filesToRemove)
{
std::filesystem::remove(i);
}
}
Aim: To design a linux shell, which shows a prompt to take input from user, creates a new process to execute that command then terminates/exits the process. Here is my code
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
using namespace std;
string cmd; //global string so cmd copied to child to execute
void HandleAsParent(){
cout<<"Linux Shell 1.0\n";
string s;
while (!exitflag) {
cout<<"myShell>";
getline(cin,cmd); //Take user input
fork();
wait(NULL);
}
}
void HandleAsChild(){
cout<<"Executing";
system(cmd.c_str());
}
int main() {
pid_t p = fork();
if(p != 0){
HandleAsParent(); //This is parent process
}
else {
HandleAsChild(); //This is child process
}
}
The problem is that, because of the first fork() call in the main,
myShell>Executing
is displayed on the first line when the program runs instead of just
myShell>
.
I am able to understand why this is happening but cannot figure out how do I stop that first child process from being executed.
Please suggest me workarounds/solutions to my problem.
Edit 1: This is one of my Assignment(for learning UNIX Processes)
questions, and It is clearly stated that the program " prompts the
user for a command, parses the command, and then executes it with a
child process "
As I already guessed, system() probably uses a combination of fork(), exec() and wait(). Out of curiosity, I googled for source code and found one on woboq.org: glibc/sysdeps/posix/system.c.
This in mind, using system(), the required child process "comes for free". So, I got this minimal sample:
#include <iostream>
void callCmd(const std::string &cmd)
{
system(cmd.c_str());
}
int main()
{
std::cout << "My Linux Shell 1.0\n"
<< "Type exit[Enter] to exit.\n";
for (;;) {
std::cout << "> ";
std::string input; std::getline(std::cin, input);
if (input == "exit") return 0;
callCmd(input);
}
}
Compiled and tested on cygwin on Windows 10:
$ g++ -std=c++11 -o mycroShell mycroShell.cc
$ ./mycroShell
My Linux Shell 1.0
Type exit[Enter] to exit.
> echo "Hello"
Hello
> exit
$
After getting this running, the system() call in callCmd() can be replaced by fork()/exec()/wait() without the necessity to change anything else.
A simplified version could look like this:
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void callCmd(const std::string &input)
{
// the pre-processing: split the input into command and arguments
std::string cmdArgs = input;
std::vector<char*> args;
char *cmd = &cmdArgs[0];
args.push_back(cmd);
for (char *c = cmd; *c; ++c) {
if (*c == ' ') {
*c = '\0'; args.push_back(c + 1);
}
}
args.push_back(nullptr); // append terminator
// simple replacement of system() (not that sophisticated)
int ret = fork();
if (ret < 0) { // failure
std::cerr << "Failed to execute '" << cmd << "'!\n";
} else if (ret == 0) { // child
execvp(cmd, args.data());
} else { // parent
waitpid(ret, nullptr, 0);
}
}
int main()
{
std::cout << "My Linux Shell 1.1\n"
<< "Type exit[Enter] to exit.\n";
for (;;) {
std::cout << "> ";
std::string input; std::getline(std::cin, input);
if (input == "exit") return 0;
callCmd(input);
}
}
Compiled and tested on cygwin on Windows 10 again:
$ g++ -std=c++11 -o mycroShell mycroShell.cc
$ ./mycroShell
My Linux Shell 1.1
Type exit[Enter] to exit.
> /usr/bin/echo "Hello"
"Hello"
> exit
$
Notes:
IMHO, the most tricky part of this is to prepare a proper argument vector for execvp.
I tried with echo "Hello" as well and it worked. This surprised me a bit as echo is a bash built-in command. I assume that it found /usr/bin/echo and used it as well as in my above output.
The error handling is rather poor – something which should be extended for serious applications.
I'm a musician and a programmer and would like to create my own program to make music.
I'll start with a console application in C++ before I make a GUI.
I'm quiet new to C/C++ and know how to make a basic console application and have read about the Win32 API.
I was looking into MSDN for multimedia in Win32 applications and I found a lot of functions for MIDI: http://msdn.microsoft.com/en-us/library/dd798495(VS.85).aspx
I can receive how many MIDI devices are plugged in this way:
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
cout << midiInGetNumDevs();
cout << " MIDI devices connected" << endl;
return 0;
}
But now i want to find out how these devices are called, with the midiInGetID function I think and a while loop. Can somebody help me with this? The function requires a HMIDIIN parameter and I don't know how I can get one since almost all the MIDI functions use this parameter.
I know this is not the most obvious topic but it would be great if someone could help me.
Thanks :)
To get information, you loop calling midiInGetDevCaps, with a first parameter varying from 0 included to the result of midiInGetNumDevs excluded. Each call fills a MIDIINCAPS struct (you pass a pointer to the struct when you call the function) with information about the Nth device. To open a device, and fill the HMIDIIN needed for other calls, you call midiInOpen with the device number (again, 0 to N-1 included) as the second parameter.
The same concept applies to output devices, except that the names have Out instead of In (and for the structures OUT instead of IN).
Ok I figured it out. I didn't know midiInGetDevCaps requires a call to the specific properties of it to return the device name.
Here is my code:
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
unsigned int devCount = midiInGetNumDevs();
cout << devCount << " MIDI devices connected:" << endl;
MIDIINCAPS inputCapabilities;
for (unsigned int i = 0; i < devCount; i++) {
midiInGetDevCaps(i, &inputCapabilities, sizeof(inputCapabilities));
cout << "[" << i << "] " << inputCapabilities.szPname << endl;
}
}
And thanks for your help!
Changing a Linux C++ program which gives the user limited file access. Thus the program chroots itself to a sandbox with the files the user can get at. All worked well.
Now, however, the program needs to access some files for its own needs (not the user's) but they are outside the sandbox. I know chroot allows access to files opened before the chroot but in this case the needed files could a few among many hundreds so it is obviously impractical to open them all just for the couple that might be required.
Is there any way to get at the files?
Copy them into the sandbox or open them all before chrooting. Seriously. If there was a way to do this, there would be a way to suborn it to allow other access and make your protection useless.
The whole point of the sandbox is to prevent exactly what you're trying to achieve.
If the files are all in 1 directory, you could use mount to bind them to a directory inside the sandbox.
mount --bind /path/to/files /sandbox/files
The you can access the files through /sandbox/files/. If you don't want the user to see them, do mount --bind /path/to/files /sandbox/.files so the .files directory is hidden
I guess that you ought to be able to split your program into two parts, one which is chroot'ed and one which isn't, and have the chroot'ed portion request files' contents from the non-chroot'ed portion via the IPC mechanism of your choice.
This is a hack, and it may be easy to get wrong, negating any benefit of a chroot. Like paxdiablo says, you're trying to get around the whole purpose of a chroot sandbox, so your options are very, very limited.
Maybe if you explained a bit more what you're trying to accomplish, we might be able to offer some other ideas. For example, SELinux and AppArmor are more flexible than chroot and may be able to give you the security you seek.
If the files you need to access are within a few directories you could open those directories before you chroot and save the file descriptors. You can then use the so-called *at functions (e.g. openat(), renameat(), etc.) to get at the individual files. Basically you are opening the files relative to the already open directory file descriptors rather than the chrooted directory.
Whether this is a safe thing to do is open to question but it should work in Linux.
EDIT: This is on the ugly side but it seems to work. You should poke around a lot more for vulnerabilities than I have. I haven't tested how dropping privileges and so forth will effect things.
#include <iostream>
#include <string>
using namespace std;
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
if (argc < 4)
{
cerr << "USAGE: " << argv[0] << " <jail directory> <freeworld directory> <filename>\n";
exit(EXIT_FAILURE);
}
const string JAILDIR(argv[1]);
const string FREEDIR(argv[2]);
string freefilename(argv[3]);
while (freefilename[0] == '/')
freefilename.erase(0, 1);
DIR *pDir;
if ((pDir = opendir(FREEDIR.c_str())) == NULL)
{
perror("Could not open outside dir");
exit(EXIT_FAILURE);
}
int freeFD = dirfd(pDir);
//cd to jail dir
if (chdir(JAILDIR.c_str()) == -1)
{
perror("cd before chroot");
exit(EXIT_FAILURE);
}
//lock in jail
if (chroot(JAILDIR.c_str()) < 0)
{
cerr << "Failed to chroot to " << JAILDIR << " - " << strerror(errno) << endl;
exit(EXIT_FAILURE);
}
//
//in jail, won't work
//
string JailFile(FREEDIR);
JailFile += "/";
JailFile += freefilename;
int jailFD;
if ((jailFD = open(JailFile.c_str(), O_RDONLY)) == -1)
{
cout << "as expected, could not open " << JailFile << endl;
perror("exected open fail");
}
else
{
cout << "defying all logic, opened " << JailFile << endl;
exit(EXIT_FAILURE);
}
//
//using this works
//
if ((jailFD = openat(freeFD, freefilename.c_str(), O_RDONLY)) == -1)
{
cout << "example did not work. Could not open " << freefilename << " Sorry!" << endl;
exit(EXIT_FAILURE);
}
else
cout << "opened " << freefilename << " from inside jail" << endl;
char buff[255];
ssize_t numread;
while (1)
{
if ((numread = read(jailFD, buff, sizeof(buff) - 1)) == -1)
{
perror("read");
exit(EXIT_FAILURE);
}
if (numread == 0)
break;
buff[numread] = '\0';
cout << buff << endl;
}
return 0;
}
To test:
echo "Hello World" >/tmp/mystuff.dat
mkdir /tmp/jail
sudo ./myprog /tmp/jail /tmp mystuff.dat