I'm trying to make a program that simlutates the terminal's nameless pipes. For example, if I want to run the command:
ls –l | grep ‘10’
would be:
./pipes ls -l - grep '10'
(I use - instead of |).
However, my program doesn't work because execvp fails (bad adress). This seems impossible to me. What am I doing wrong? Any help would be welcome!
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
void np_exec(char* cmd, char** argv)
{
int fd[2];
while(*(++argv) != NULL)
{
pipe(fd);
int pid = fork(); //parent executes
if(pid < 0)
{
printf("Error forking");
exit(1);
}
if(pid != 0) // parent
{
dup2(fd[1],1);
close(fd[0]);
if (execvp(cmd, *argv) == -1)
{
perror("execvp failed");
}
}
else
{
dup2(fd[0],0);
close(fd[1]);
}
}
}
int main(int argc, char** argv)
{
assert(strcmp(argv[argc-1], "-"));
int i;
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "-"))
{
argv[i] = NULL;
np_exec(argv[1], &argv[1]);
argv = &argv[i];
argc -= i;
i = 0;
}
}
char* args[argc];
args[argc-1] = NULL;
for (i = 1; i < argc; ++i) {
args[i-1] = argv[i];
}
if (execvp(args[0], args) == -1)
perror("execvp failed");
return;
}
Replace:
if (execvp(cmd, *argv) == -1)
by:
if (execvp(cmd, argv) == -1)
Notes:
a) is the warnign level you use high enough?
b) you must add a "#include" for "execvp". In this way, the compiler will find by itself this error.
c) last return statement must be "return 0". Again, compiler must warning you of this subject.
Related
I am trying to create a pipe program. by passing back and forth between two pipes. However when the input becomes 6 or more, I get error: standard input bad file descriptor. I cannot figure out where the issue might be.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int rc;
char *myargs[2];
myargs[1] = NULL;
int status;
int nprocess=argc-1;
int n;
int fp[2];
if (argc > 4) {
int i;
int myfp[2];
status=pipe(myfp);
rc = fork();
if (rc==0){
close(myfp[0]);
dup2(myfp[1], STDOUT_FILENO);
myargs[0] = argv[1];
execvp(myargs[0], myargs);
} else {
waitpid(rc, &status, 0);
int myfp1[2];
status = pipe(myfp1);
for (n = 2; n <= nprocess-1; n++) {
rc = fork();
if (rc == 0 && n % 2 == 0) {
dup2(myfp[0], STDIN_FILENO);
dup2(myfp1[1], STDOUT_FILENO);
close(myfp[1]);
close(myfp1[0]);
myargs[0] = argv[n];
execvp(myargs[0], myargs);
} else if (rc == 0 && n % 2 != 0) {
dup2(myfp[1], STDOUT_FILENO);
dup2(myfp1[0], STDIN_FILENO);
close(myfp[0]);
close(myfp1[1]);
myargs[0] = argv[n];
execvp(myargs[0], myargs);
} else if (n % 2 == 0) {
close(myfp[1]);
close(myfp[0]);
close(myfp1[1]);
waitpid(rc, &status, 0);
status = pipe(myfp);
} else {
close(myfp[1]);
close(myfp1[0]);
close(myfp1[1]);
waitpid(rc, &status, 0);
status=pipe(myfp1);
}
}
}
}
return 0;
}
Example input would be ./pipe ls cat wc wc wc wc
Hey I have to write a small process launcher for uni.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]){
pid_t pid;
if((pid = fork()) < 0){
return 0;
}
else if(pid == 0){
if(execvp(*argv, argv) < 0){
return 0;
}
}
return 0;
}
This is my program. I want to call it like ./process-launcher firefox --browser to start a new firefox process.
I think when I start the programm like this there should be a process of firefox in my system monitoring but it isn't
How do I get this?
Compiling with:
clang -o process-launcher process-launcher.c
What is in *argv? Your launcher name...
So when executing your code as is, you only relaunch your launcher...
Solution: ++argv;, it will pass the second parameter to execvp:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]){
pid_t pid;
if((pid = fork()) < 0){
return 0;
}
else if(pid == 0){
++argv;
printf("execvp(%s, ...)\n", *argv);
if(execvp(*argv, argv) < 0){
return 0;
}
}
return 0;
}
I am trying to run three execv("./test",execv_str) in parallel. And I need to print out success message when each of execv() completes successfully.
But now I get result as following:
username#username:~/Desktop/$./test -p
SUCCESS
SUCCESS
SUCCESS
username#username:~/Desktop/$ TESTING
TESTING
TESTING
The expected result will be:
username#username:~/Desktop/$./test -p
TESTING
SUCCESS
TESTING
SUCCESS
TESTING
SUCCESS
username#username:~/Desktop/$
Here is the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int fork_execv()
{
int status;
pid_t pid;
pid = fork();
/* Handling Child Process */
if(pid == 0){
char* execv_str[] = {"./test", NULL};
if (execv("./test",execv_str) < 0){
status = -1;
perror("ERROR\n");
}
}
/* Handling Child Process Failure */
else if(pid < 0){
status = -1;
perror("ERROR\n");
}
return status;
}
int main(int argc, char *argv[]){
if (argc == 1){
sleep(5);
printf("TESTING\n");
}
else{
int i;
for(i = 0; i < 3; ++i){
if (fork_execv() != -1){
printf("SUCCESS\n");
}
}
}
}
How to modify my code to make it work?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int fork_execv()
{
int status;
pid_t pid;
pid = fork();
/* Handeling Chile Process */
if(pid == 0){
char* execv_str[] = {"./test", NULL};
if (execv("./test",execv_str) < 0){
status = -1;
perror("ERROR\n");
}
}
/* Handeling Chile Process Failure */
else if(pid < 0){
status = -1;
perror("ERROR\n");
}
return pid;
}
void handler(int sig){
printf("SUCCESS\n");
}
int main(int argc, char *argv[]){
if (argc == 1){
sleep(5);
printf("TESTING\n");
}
else{
int i;
pid_t process_id;
for(i = 0; i < 3; ++i){
if ((process_id = fork_execv()) != -1){
if(process_id != 0){
signal(SIGCHLD, handler);
waitpid(process_id, NULL, 0);
}
}
}
}
}
Here what I would do. After the fork, I return the pid, check if it isn't 0 (so we are in the father process) and make the father wait for the son. To print "success", I bind the SIGCHLD signal that is triggered when a child process ends. Note that this is a little overkill and put print after the waitpid would have done the job. (But I like to bind signal.)
I wrote a program that aims to simulate the terminal, more specifically, unnamed pipes. For example, I can simulate the terminal command cat file | grep 'aa'
using the command
./myterminal cat file - grep 'aa'
(I separate the arguments with - instead of |). And it works perfectly. However, if I try to use the command
./myterminal cat file - grep 'aa' - grep 'bb'
I get the error messege:
Usage: aa [OPTION] ... PATTERN [FILE]...
Try 'aa--help' for more information.
So obviously something is wrong. When I try the command
./myterminal cat file - grep 'aa' 'file' - grep 'bb' 'file'
The correct line from the file is printed -- however, so is the error message. What is happening here? Clearly something is wrong with my program, I just dont understand what. The program itself is so simple I'm not sure what's going wrong here.
The code itself is:
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
void np_exec(char* cmd, char** argv)
{
int fd[2];
while(*(++argv) != NULL)
{
pipe(fd);
int pid = fork(); //parent executes
if(pid < 0)
{
printf("Error forking");
exit(1);
}
if(pid != 0) // parent
{
dup2(fd[1],1);
close(fd[0]);
if (execvp(cmd, argv) == -1)
{
perror("execvp failed");
}
}
else
{
dup2(fd[0],0);
close(fd[1]);
}
}
}
int main(int argc, char** argv)
{
assert(strcmp(argv[argc-1], "-"));
int i;
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "-"))
{
argv[i] = NULL;
np_exec(argv[1], &argv[1]);
argv = &argv[i];
argc -= i;
i = 0;
}
}
char* args[argc];
args[argc-1] = NULL;
for (i = 1; i < argc; ++i) {
args[i-1] = argv[i];
}
if (execvp(args[0], args) == -1)
perror("execvp failed");
return 0;
}
Does anyone know where I'm wrong?
I'm trying to create a c program that takes an executable and its arguments and runs them using execve, and then does some other stuff that shouldn't matter. The problem I'm having is that execve won't work when calling it on an exectuable assembly file. I think the problem is with my path because I can get the unix shell commands to work, but I can't get executables in the current directory (using ./spy ./executableName where spy is the name of my c program) to run. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
extern char **environ;
int main(int argc, char* const argv[]) {
pid_t pid;
char filename[50];
char* arglist[argc];
int i = 1,count = 0;
int status;
strcpy(filename, "/bin/");
strcat(filename,argv[1]);
for(i = 1; i< argc; i++)
arglist[i-1] = argv[i];
arglist[argc-1] = 0;
arglist[0] = filename;
if (argc == 1) {
fprintf(stderr,"usage : %s <prog> ...\n",argv[0]);
return -1;
}
pid = fork();
if(pid == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
if(execve(filename, arglist, 0) < 0)
fprintf(stdout,"Invalid file.");
}
else {
while(1) {
waitpid(pid,&status,0);
if (WIFEXITED(status))
break;
ptrace(PTRACE_SINGLESTEP, pid,NULL, NULL);
count++;
}
}
return 0;
}
From the source you posted it looks as if you were always prefixing the name passed as parameter with /bin/. So if the file isn't in /bin/ it can not be found, nor run.
Just change these two lines:
strcpy(filename, "/bin/");
strcat(filename,argv[1]);
to be:
strcpy(filename,argv[1]);
Note that having applied this modification the program to be run needs to be specified with its full path.
So to run ls you need to do specfify /bin/ls as parameter to the program.
Some other comments:
So avoid buffer a overflow for long path/file names change:
char filename[50];
to be:
char filename[PATH_MAX];
To get more detailed information on why an execve() might have failed change:
if(execve(filename, arglist, 0) < 0)
fprintf(stdout,"Invalid file.");
to be:
if(execve(filename, arglist, (char*) 0) < 0)
perror("execve() failed");
To detect a possible failure of forking do change:
pid = fork();
to become:
if (-1 == (pid = fork())) then
{
perror("fork() failed");
}
else