I am trying to write a program that will fork, then open a file and execute it. The file it should execute is called child and it has been compiled. When I type ./child, it runs. However, when I run this program it does not execute the child program and I am prompted with the error message I put in "Execution failed". What I am doing wrong?
This is my parent class
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int main (int argc, char **argv)
{
pid_t parent = getpid();
pid_t pid = fork();
if (pid == -1)
{
// error, failed to fork()
}
else if (pid > 0)
{
int status;
waitpid(pid, &status, 0);
}
else
{
int var = execvp("./child", NULL);
if(var < 0)
{
printf("Execution failed");
}
}
exit(0); // exec never returns
}
This is the child
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv)
{
printf ("Im the child");
exit (0);
}
I actually don't know what you are doing wrong. After a copy and a compilation (and several warning complains) your code runs fine (GCC 7.2).
Obviously, child must be in the same working directory in which you run your main executable (the one that forks).
But probably I would write that code in this way, but I'm not an expert in forking:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
extern int errno;
int main () {
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
if (pid == 0) {
int ret = execl("./child", "", (char *)NULL);
if(ret < 0) {
fprintf(stderr, "%s\n", strerror(errno));
return 1;
}
} else {
wait(NULL);
}
return 0;
}
At least it tells you which error execl has encountered.
Related
I would like to create a named pipe in the parent process and after write a string to it in the child process and finally read this string in the parent process. When run the program I dont get back the prompt like still waiting for end of child process. Why the child process not finished?
Current output:
Expected output:
(picture created without multiprocesses)
My source code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
int main() {
int pipefd[2];
pid_t cpid;
char szoveg[32];
int fd, ret;
char buf[32];
buf[0]=0;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(-1);
}
if (cpid == 0) {
printf("%d: Child process\n",getpid());
strcpy(buf,"Some text \0");
printf("%d:write to fifo: %s:%ld\n",getpid(),buf,strlen(buf));
write(fd,buf,strlen(buf));
exit(0);
} else {
printf("%d: Parent process\n",getpid());
ret=mkfifo("FifoName",00666);
if (ret == -1) {
perror("mkfifo()");
exit(-1);
}
fd=open("FifoName",O_RDWR);
if (fd == -1) {
perror("open() error!");
exit(-1);
}
wait(NULL);
ret=read(fd,buf,32);
printf("%d:read() Read %d bytes: %s\n",getpid(),ret,buf);
close(fd);
unlink("FifoName");
exit(0);
}
}
William Pursell right. The problem was the missing fd=open("FifoName",O_RDWR); line from child process.
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 am learning C and have run into a small problem. After reading about fork() bomb on Wikipedia and on StackOverflow. I wanted to implement the same, but using command line args.
I want to endlessly call firefox/chrome, but unable to do the same in my below program. Any assistance would be greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
int main(int argc, char **argv)
{
pid_t pid;
char *parmList[] = {"firefox", "index.html", NULL};
int a;
if ((pid = fork()) == -1)
{
perror("fork failed");
}
if (pid == 0)
{
a = execvp("/usr/bin/firefox", parmList);
fprintf(stdout, "execvp() returned %d\n", a);
fprintf(stdout, "errno: %s (%d).\n", strerror(errno), errno);
}
else
{
waitpid(pid, 0, 0);
}
return 0;
}
You should clarify what error you're getting, since I don't want to run a fork bomb, but the code you wrote doesn't bomb (call fork() within a loop). It spawns one process, waits nicely, and quits.
I'm trying to run a test program that will display the process of a requested pid. If the pid is not inserted, it's suppose to get the process for pid 1 which is init. Somehow when I run it on hp-ux itanium, it cannot display the process. This only happens on hp-ux itanium for pid 1. For other pid and platform, it works just fine. Here are the code that I think is related:
This is the test file
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "procname.h"
int main(int argc, char **argv)
{
pid_t pid;
char proc[PROCNAME_SZ];
if (argc==2) {
pid = atoi(argv[1]);
if (pid<1) {
printf("Invalid pid\n");
exit(1);
}
} else {
pid = 1;
}
if (get_procname(pid, proc, sizeof(proc))!=0) {
printf("Error retrieving process name: %s\n", strerror(errno));
printf("proc = %s\n",proc);
printf("pid is = %d\n",pid);
exit(1);
}
if (argc==2) {
printf("Process name = %s\n", proc);
} else {
printf("Checking if procname(1) have init...");
if (strstr(proc, "init")) {
printf("OK (%s)\n", proc);
exit(0);
} else {
printf("Failed (%s)\n", proc);
exit(1);
}
}
return 0;
}
This is the .c file
#include <errno.h>
#include "procname.h"
#include "log.h"
#ifdef HPUX
# include <sys/param.h>
# include <sys/pstat.h>
# include <sys/unistd.h>
#endif
int get_procname(pid_t pid, char *buf, size_t n)
{
#ifdef HPUX
struct pst_status pst;
if (pstat_getproc(&pst, sizeof(pst), (size_t)0, pid) != -1) {
memcpy(buf, pst.pst_cmd, n - 1);
buf[n-1] = 0;
} else {
return -1;
}
#endif
return 0;
}
This is the output that I got on hp-ux itanium:
./test_procname 1
Error retrieving process name: Value too large to be stored in data type
proc =
pid is = 1
This is the result that I got on hp-uxmp
./test_procname 1
Process name = init
The pid are just the same, but somehow it cannot recognized the init on hp-ux itanium. The size for printing the string are more than enough to just print init.
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