All, the first part of my homework assignment is simply a demo program that I need to compile, and then modify. It was provided by the teacher, however I simply cannot get it to compile using g++. I will be creating a make file at the end of the assignment, but for the moment I am simply trying to test it out, and am having no luck. I've tried the most basic g++ command: g++ -o main TwoPipesTwoChildren.cpp . Can someone please help? I can't even get started on this until I can get this working.
// description: This program will execute "ls -ltr | grep 3376"
// by using a parent and child process
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char **argv){
printf("TEST");
int status;
int childpid;
char *cat_args[] = {"ls", "-ltr", NULL};
char *grep_args[] = {"grep", "3376", NULL};
// create one pipe to send the output of "ls" process to "grep" process
int pipes[2];
pipe(pipes);
// fork the first child (to execute cat)
if((childpid = fork()) == -1)
{
perror("Error creating a child process");
exit(1);
}
// replace cat's stdout with write part of 1st pipe
if (childpid == 0)
{
dup2(pipes[1], 1);
printf("AFTER FORK CHILD");
//close all pipes (very important!); end we're using was safely copied
close(pipes[0]);
close(pipes[1]);
execvp(*cat_args, cat_args);
exit(0);
}
else
{
// replace grep's stdin with read end of 1st pipe
dup2(pipes[0], 0);
close(pipes[0]);
close(pipes[1]);
execvp(*grep_args, grep_args);
}
return (0);
}
Related
I have tried to write a program that run in ubuntu terminal .Program will open a new gnome terminal and run command in that new terminal to open new abcd.txt using vim.And then when i Ctrl+C in the first terminal which run the program ,new gnome terminal will shut vim down and have an announcement in the first terminal
I have tried system("`gnome-terminal`<< vim abcd.txt");
and this system("vim abcd.txt>>`gnome-terminal`");
but the new one terminal cannot recieve command
My full code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
int loop=1;
void DEF()
{
system("kill -9 pidof vim");
loop=0;
}
void *subthreads(void *threadid)
{
loop=1;
long tid;
tid=(long)threadid;
system("`gnome-terminal`<< vim abcd.txt");
signal(SIGINT,DEF);
while(loop){}
pthread_exit(NULL);
}
void main()
{
int loop=1;
pthread_t threads;
int check;
long tID;
check= pthread_create(&threads,NULL,&subthreads,(void*)tID);
while(loop){}
printf("Ctrl+C is pressed!\n");
}
Not sure what you are trying to achieve in the end. But here are a few ideas, starting from your code:
The terminal command (in system()) should be something like Mark Setchell pointed out, like for example system("gnome-terminal -e vim file.txt");
The system() command is blocking further execution of your code, so the call to signal() is not happening until you terminate the system() call.
pidof is not working on my Linux system. I would use pkill <program>. Still, that would kill all running instances of , for example vim or your terminal.
You are declaring the variable loop in the global scope first and then redeclaring it in main(). If you really want to use it as a global variable, it should just be loop=1 in main().
You are not using the variable tid for anything.
Here is an improved version of your program, with additional printf calls to explain to the user what is happening. I also used xterm and nano because I don't have gnome-terminal, and I didn't want to interfere with my running instance of vim. But it still is maybe not exactly what you are trying to do. The main problem is that system("xterm -e sh &") is blocking and when you press Ctrl-C, that system call will terminate xterm so that the def() function will do nothing when it is called later.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
int loop = 1;
void def()
{
printf("In def\n");
system("pkill xterm");
loop=0;
}
void *subthreads(void *threadid)
{
printf("Starting subthread\n");
loop = 1;
long tid;
tid = (long)threadid;
signal(SIGINT, def);
system("xterm -e sh -c nano &"); // Note: xterm will still exit when you press Ctrl-C
printf("Terminal exited in subthread\n");
while (loop);
printf("Exited loop in subthread\n");
pthread_exit(NULL);
}
void main()
{
pthread_t threads;
int check;
long tID;
check = pthread_create(&threads, NULL, &subthreads, (void*)tID);
printf("In main after thread creation\n");
while (loop);
printf("Ctrl+C is pressed!\n");
}
Another option is to use fork() instead of pthread to split into a separate process. (Note that processes are like separate applications while threads are processor threads in the same application.)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
void def()
{
system("pkill nano");
printf("def(): Killed nano\n");
}
int subprocess()
{
signal(SIGINT, def);
pid_t parent_id = getpid(); // Get process ID of main process
fork(); // Fork into two identical copies of the running app.
if (getpid() != parent_id) { // The part in the if block is only done in the second process!
system("xterm -e sh -c nano &");
printf("subprocess(): system call ended in forked process\n");
exit(0);
}
}
int main()
{
subprocess();
printf("Entering while loop in main process\n");
while (1);
printf("Exited main thread\n");
}
The one flaw with this version is the same as the previous one: when Ctrl-C is pressed, xterm/nano is killed and def() will subsequently do nothing except catch any Ctrl-C done afterwards.
If you explain further what your final goal is, maybe I can give some suggestions.
Like, why do you want to start vim in a terminal from a C application and then kill vim? Do you want to kill the whole terminal or only vim?
I use chdir() to switch the directory, and then use execvp() to execute "java Main". I'm sure there is Main.class, but something went wrong. I want to know why.
#include <cstdio>
#include <unistd.h>
using namespace std;
int main(){
char buf[80];
getcwd(buf,sizeof(buf));
printf("current working directory: %s\n", buf);
chdir("/home/keane/Judge/temp");
getcwd(buf,sizeof(buf));
printf("current working directory: %s\n", buf);
char *array[3];
array[0] = "java";
array[1] = "Main";
array[2] = NULL;
execvp("java", array);
return 0;
}
the error is could not find the main class , and I can run java Main in that directory.
What drives me crazy is that I can't use system("java Main"), and the error is that Error: Could not find or load main class Main, and it's just like this on my computer
update:
#include <unistd.h>
#include <cstdlib>
int main(){
chdir("/home/keane/Judge/temp");
system("pwd");
system("ls");
system("java Main");
return 0;
}
the output on console is:
/home/keane/Judge/temp
1.out 3.out 5.out Main.class stdout_spj.txt
2.out 4.out ce.txt Main.java
Error: Could not find or load the main class Main
my final solution is to reboot the computer and add -cp . to the java command.
althought I don't why is necessary.
thanks everyone!
This works as intended on my system, maybe you need to add -cp . to your java call.
EDIT: to elaborate: -cp (for classpath) tells java where to look for user provided .class files. This does not necessarily include the current working directory by default.
The execution of execvp() is non-blocking and takes ownership of the caller, that means that when it starts if the program ends too quickly you will never be able to see the result, to solve this I use fork(). The wait is just to avoid using sleep as I used at the begining. Its all in c.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char** argv){
char buf[80];
getcwd(buf,sizeof(buf));
printf("current working directory: %s\n", buf);
chdir("/home/");
getcwd(buf,sizeof(buf));
printf("current working directory: %s\n", buf);
char *array[3] = {"java", "Main", NULL};
if(fork() == 0) {
if(execvp("java", array) < 0) {
fprintf(stderr, "Error spawning command: %s\n", strerror(errno));
}
} else {
printf("Command spawned\n");
wait(NULL); // Wait to the forked process to end (avoid using sleep)
}
return 0;
}
I am trying to print the path of the current directory using
this
execl ("/bin/pwd", "pwd", NULL);
output: /home/user/Ubuntu
and want to print a desired text before the current path.
for example:
my name /home/user/ubntu
how this will be done?
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
using namespace std;
int main(){
string command;
while(command != "exit"){
cout<< "B-17235"<<return execl ("/bin/pwd", "pwd", NULL);
cin>> command;
}
return 0;
}
Think that the majority of Unix-Linux-Gnu commands are written in C or C++. Generally there are direct API calls either system calls (man 2) or standard C library (man 3) to get the information or do the job.
To get working directory, just use getcwd() as suggested by alk.
char buffer[256];
if (NULL == getcwd(buffer, sizeof(buffer))) {
perror("can't get current dir");
return 1;
}
If you wanted to get the output of a more complex command, the most direct way would be to use popen that encloses the fork, exec, and pipe management for you :
FILE *fd = popen("/bin/pwd", "r");
char buffer[256];
if (fgets(buffer, sizeof(buffer), fd) == NULL) {
perror("can't read command");
return 1;
}
if (buffer[strlen(buffer) - 1] != '\n') {
fprintf(stderr, "path too long";
return 1;
}
pclose(fd);
// ok the working directory is is buffer
You should not use that for a command as simple as pwd.
And don't forget : man is your friend ! man getcwd and man popen will give you plenty of information ...
I am trying to print the path of the current directory
Use the library function getcwd().
To have the function available it might be necessary to #define _XOPEN_SOURCE 500 or similar (please see the man-page linked above for details on this).
I am running the code below and I cannot redirect to a file. The file is made, but nothing is put into it. If I remove the last dup2(saveout,1) statement, I can create and write into the file, but I cannot get back to the terminal, which is important. As soon as I put the dup2(saveout,1) back in my code, the redirection stops working, but I can get back to the terminal. I do not understand why this is happening. I would like to redirect and go back into the terminal.
main.cpp
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
using namespace std;
void printmessage() {
printf("this is the message\n");
}
int main(int argc, char** argv) {
int saveout;
int fd;
saveout = dup(1);
for (int i = 0; i < 10; i++) {
fd = creat("/home/carl/example.txt",O_CREAT|O_APPEND);
dup2(fd, 1);
close(fd);
printf("Testing the message");
printmessage();
dup2(saveout,1);
close(saveout);
}
return 0;
}
This is a file rights issue, you should read the man pages of the functions you are using.
creat() takes as first argument the filename, and as second the file creation rights, not its opening mode.
The creat() functions is a simple open() call, with some particular flags, so that you'll just have to set up the rights.
if you want to open your file, and create it if he doesn't exists, use
open(filename, O_CREAT | O_RDWR | O_APPEND, 0600) for example, or
creat(filename, 0600),
which is mostly its equivalent, but you wont be able to append text, as "creat() is equivalent to open() with flags equal to O_CREAT | O_WRONLY | O_TRUNC"
The second dup2(saveout,1); will fail because you closed saveout.
printf is buffered by default. (line-by-line for output to a tty, perhaps differently for output to something else). Before both your calls to dup2(..., 1), you should flush with fflush:
fflush(stdout);
I am using following code for extracting output of system command .
I have not set path for "pic" in PATH variable. and i want to store
output of command "which pic" and do not want to display it on console.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main ()
{
FILE *fp;
int status;
char path[1035];
char *command = "which pic";
/* Open the command for reading. */
fp = popen(command, "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(0);
}
/* Read the output a line at a time - output it. */
while (fgets(path, sizeof(path)-1, fp) != NULL) {
cout<<"<<<<<<<<<<,"<<endl;
printf("%s", path);
}
/* close */
pclose(fp);
return 0;
}
but it displaying following output in console :
which: no pic in(/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin)
Run "which pic 2>&1" as your command. You want to capture all output from which, including its errors (which are sent to stderr).