wait(&status) always return 0 - c

I'm try to get exit status of child process but always gets 0.
what I'm doing wrong, is this not the way?
here is my code, tokens = an commands array.
thanks
int execute(char** tokens)
{
pid_t pid;
int status;
pid = fork();
if (pid == -1)
{
fprintf(stderr,"ERROR: forking child process failed\n");
return -1;
}
// Child process
if (pid == 0)
{
// Command was failed
if (execvp(*tokens, tokens) == -1)
{
fprintf(stderr, "%s:command not found\n", *tokens);
return 255;
}
}
else
{
pid = wait(&status);
status = WEXITSTATUS(status);
}
return status;
}
always:
status = 0.
what I need to change?

You'd probably want to exit(255) right away to ensure that the correct status is returned. Also wait is very probable to get EINTR. Also, the return status is meaningful only if WIFEXITED(status), otherwise you shouldn't rely on it:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
int execute(char** tokens)
{
pid_t pid;
int status;
pid = fork();
if (pid == -1)
{
fprintf(stderr,"ERROR: forking child process failed\n");
return -1;
}
// Child process
if (pid == 0)
{
// Command was failed
if (execvp(*tokens, tokens) == -1)
{
fprintf(stderr, "%s: command not found\n", *tokens);
exit(255);
}
}
else {
while (1) {
pid = wait(&status);
if (pid == -1) {
if (errno == EINTR) {
continue;
}
perror("wait");
exit(1);
}
break;
}
if (WIFEXITED(status)) {
int exitcode = WEXITSTATUS(status);
printf("%d\n", exitcode);
}
else {
printf("Abnormal program termination");
}
}
return status;
}
int main() {
char *args[] = {
"/bin/cmd_not_found",
"Hello",
"World!",
0
};
execute(args);
}

Related

For some reason im getting wrong result using fork

The program creates a child proccess and the child does the proper work in order to see if its pid is even or odd
And for some reason even if the pid is even i get that it is odd , also the parent waits for child
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
pid_t pid, mypid, cpid;
int flag;
pid = getpid();
printf("Process %d creates new process\n\n", pid);
cpid = fork();
if (cpid == 0) {
cpid=getpid();
printf("\n----[%d] child\n", cpid);
if (cpid % 2 == 0) {
flag = 1;
} else {
flag = 0;
}
exit(0);
} else if (cpid != 0) {
wait(NULL);
mypid = getpid();
printf("\n[%d] parent of [%d]\n", mypid, cpid);
if (flag == 1) {
printf("\nThe child pid is even");
} else if(flag ==0) {
printf("\nThe child pid is odd");
} else {
printf("\nSomething went wrong");
}
} else {
perror("Fork failed");
}
return 0;
}

Generating a process tree with fork()

I am required to create a process tree with relationships expressed as in the picture.
The problem is I must create all "nodes" in the order of the alphabet. I have gotten this far but my order is not consistent. I believe I am using waitpid incorrectly?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char **argv)
{
pid_t pidA, pidB, pidC, pidD, pidE, pidF, pidG, pidI;
pidA = fork();
if (pidA < 0)
{
perror("A");
exit(1);
}
else if (pidA == 0)
{
printf("%d: A\n", getpid());
pidB = fork();
if (pidB < 0)
{
perror("B");
exit(1);
}
else if (pidB == 0)
{
printf("%d: B\n", getpid());
waitpid(pidD, NULL, 0);
pidE = fork();
if (pidE < 0)
{
perror("E");
exit(1);
}
else if (pidE == 0)
{
printf("%d: E\n", getpid());
waitpid(pidG, NULL, 0);
pidI = fork();
if (pidI < 0)
{
perror("E");
exit(1);
}
else if (pidI == 0)
{
printf("%d: I\n", getpid());
}
else
{
;
}
}
else
{
pidF = fork();
if (pidF < 0)
{
perror("F");
exit(1);
}
else if (pidF == 0)
{
printf("%d: F\n", getpid());
}
else
{
;
}
}
}
else
{
pidC = fork();
if (pidC < 0)
{
perror("B");
exit(1);
}
else if (pidC == 0)
{
printf("%d: C\n", getpid());
waitpid(pidF, NULL, 0); // !
pidG = fork();
if (pidG < 0)
{
perror("G");
exit(1);
}
else if (pidG == 0)
{
printf("%d: G\n", getpid());
}
else
{
;
}
}
else
{
pidD = fork();
if (pidD < 0)
{
perror("B");
exit(1);
}
else if (pidD == 0)
{
printf("%d: D\n", getpid());
}
else
{
;
}
}
}
}
else
{
;
}
return 0;
}
Output is not consistent so I think this part wouldn't help much.
5644: A
5645: B
5646: C
5647: D
5648: G
5650: F
5649: E
5651: I
The principal problem here is that waitpid only suffices for synchronization when all of the processes are linearly related (i.e., parent process, child process, "grandchild" process, etc.).
However, your processes, as exhibited by the diagram, are not linearly related. You can see this issue arise when you call waitpid(pidD, NULL, 0); from within the B process. Not only is pidD not defined in this context but the D process is not a child of the B process and so waitpid is inappropriate.
#EOF makes a good point that trying to run multiple processes in series defeats the purpose of having multiple processes. However, if you just want to do this exercise as a fun brain teaser, I'd recommend setting up pipes in the original process and then closing the write end when the appropriate process wants to signal that it has exited. The process that is waiting for the first process to end can call select on the read end.

Fork and Pipe program not working properly

I'm trying to code a simple fork() and pipe() program which gets input from the user and outputs it through the pipe in the childprocess. But somehow I'm not getting the result I wished to get.
The first input works fine, for example I type in "Hi" and get the result "Prozessmanager: Hi", but as soon as I try to input the next string, it crashes or somehow stops working until I input a "Q" which exits my Program.
I tried to debug it and got the result, that I'm trying to write into a broken pipe.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
//#include <signal.h>
#define BUFSIZE 512
//int clock = 0;
//void handler(int signum) {
//clock++;
//printf("Clock: 00:00:%d\n", clock);
//}
int main(int argc, char** argv) {
pid_t prozessmanager;
pid_t reporter;
int pipefd[2];
int status;
char str[BUFSIZE];
char buf[BUFSIZE];
if ((pipe(pipefd)) == -1) {
perror("pipe() error");
exit(1);
}
if ((prozessmanager = fork()) == -1) {
perror("fork() error");
exit(1);
} else if (prozessmanager == 0) { //Prozessmanager prozess
while (1) {
//signal(SIGALRM, handler);
//while(1){
//alarm(1);
//}
close(pipefd[1]);
read(pipefd[0], buf, sizeof (buf));
/*if (*buf == 'S') {
//handler(clock);
} else {*/
if (*buf == 'P') {
if ((reporter = fork()) == -1) {
perror("fork() error");
exit(1);
} else if (reporter == 0) { //Reporter prozess
printf("Im a Report Prozess, PID: %d\n", getpid());
exit(0);
} else { //Prozessmanager waits for Reporter
wait(&status);
printf("Report terminated, PID: %d\n", reporter);
break;
}
} else if (*buf == 'Q') {
printf("Exit Prozessmanager, PID: %d\n", getpid());
exit(0);
} else {
printf("Prozessmanager: %s", buf);
break;
}
//}
}
} else { //Kommandant prozess
while (1) {
close(pipefd[0]);
fgets(str, 80, stdin);
write(pipefd[1], str, sizeof (str));
if (*str == 'Q') {
break;
}
}
wait(&status);
printf("Exit Kommandant, PID: %d\n", getpid());
exit(0);
}
return (0);
}

PseudoTerminal C - How To

I am currently trying to make an application that will receive information from a client and send it to be executed in a server. For that I need to use PseudoTerminals.
I followed the example from a book and I ended up with this code
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
int ptyMasterOpen(char *slavName, size_t snLen)
{
int masterFd, savedErrno;
char *p;
masterFd = posix_openpt(O_RDWR | O_NOCTTY);
printf("Master: %d \n", masterFd);
if(masterFd == -1)
return -1;
if(grantpt(masterFd) == -1 || unlockpt(masterFd) == -1)
{
savedErrno = errno;
close(masterFd);
errno = savedErrno;
return -1;
}
p = ptsname(masterFd); /*Get the name of the of the slave*/
if(p == NULL)
{
savedErrno = errno;
close(masterFd);
errno = savedErrno;
return -1;
}
printf("Slave: %s \n", p);
//*
if(strlen(p) < snLen)
{
strncpy(slavName, p, snLen);
}
else
{
close(masterFd);
errno = EOVERFLOW;
return -1;
}
//*/
return masterFd;
}
pid_t ptyFork(int *masterFd, char *slavName, size_t snLen)
{
int mfd, slaveFd, saveErrno;
pid_t childPid;
char slname[MAX_SNAME];
char cIn[100], cOut[100];
int out = -1, in = -1;
mfd = ptyMasterOpen(slname, MAX_SNAME);
if(mfd == -1)
return -1;
if(slavName != NULL)
{
if(strlen(slname) < snLen)
{
strncpy(slavName, slname, snLen);
}
else
{
close(mfd);
errno = EOVERFLOW;
return -1;
}
}
childPid = fork();
if(childPid == -1)
{
saveErrno = errno;
close(mfd);
errno = saveErrno;
return -1;
}
if(childPid != 0)
{
*masterFd = mfd;
return childPid;
}
close(mfd);
slaveFd = open(slname, O_RDWR);
if(slaveFd != -1)
{
sprintf(cOut, "/tmp/out%d", slaveFd);
sprintf(cIn, "/tmp/in%d", slaveFd);
mkfifo(cOut, S_IRUSR|S_IWUSR);
out = open(cOut, O_RDWR|O_TRUNC|O_NONBLOCK);
mkfifo(cIn, S_IRUSR|S_IWUSR);
in = open(cIn, O_RDONLY|O_TRUNC);dup2(out, STDERR_FILENO);
dup2(out, STDOUT_FILENO);
dup2(in, STDIN_FILENO);
}
else
{
printf("Problem with slave\n\r");
fflush(stdout);
}
//*
if(dup2(slaveFd, STDIN_FILENO) != STDIN_FILENO || dup2(slaveFd, STDERR_FILENO) != STDERR_FILENO || dup2(slaveFd, STDOUT_FILENO) != STDOUT_FILENO)
{
printf("Error on duplicating Files");
close(slaveFd);
exit(0);
}
else
{
dup2(out, STDERR_FILENO);
dup2(out, STDOUT_FILENO);
dup2(in, STDIN_FILENO);
}
//*/
return slaveFd;
}
The problem is:
sprintf(cOut, "/tmp/out%d", childPid);
sprintf(cIn, "/tmp/in%d", childPid);
always return 0 even when I print them in main and they are values like 952...
also using echo "ls" > "/tmp/inxx" and cat /tmp/outxx does nothing.
I believe the problem is when the fork is done, the variables lose their values or something, because, it prints the error messages now, without the while(1) on main
int main(int argc, const char * argv[])
{
// insert code here...
int masterFd;
pid_t slaveFd;
char slavName[MAX_SNAME];
slaveFd = ptyFork(&masterFd, slavName, MAX_SNAME);
//close(masterFd);
//while(1);
return 0;
}
Can anyone help?
Thanks

how to move the process in foreground [duplicate]

This question already has answers here:
How to bring a child process running in the background to the foreground
(3 answers)
Closed 9 years ago.
I write similarity of the command bash interpreter.
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <wait.h>
#include "shell.h"
#include <string.h>
char *infile;
char *outfile;
char *appfile;
struct command cmds[MAXCMDS];
char bkgrnd;
int k = 0;
static void my_wait(pid_t pid, pid_t bkgrnds[]);
int main(int argc,char *argv[])
{
int i;
char line[1024]; /* allow large command lines */
int ncmds;
char prompt[50]; /* shell prompt */
pid_t bkgrnds[1024]; /* for fg */
/* PLACE SIGNAL CODE HERE */
signal(SIGINT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
sprintf(prompt,"[%s] ",argv[0]);
while (promptline(prompt, line, sizeof(line)) > 0)
{ /* l eof */
if (0 >= (ncmds = parseline(line)))
{
continue; /* read next line */
}
#ifdef DEBUG
{
int i, j;
for (i = 0; i < ncmds; i++)
{
for (j = 0; NULL != cmds[i].cmdargs[j]; j++)
{
fprintf(stderr, "cmd[%d].cmdargs[%d] = %s\n", i, j, cmds[i].cmdargs[j]);
}
fprintf(stderr, "cmds[%d].cmdflag = %o\n", i, [i].cmdflag);
}
}
#endif
{
int previous_pipe_output = -1;
int pipeline_start = 0;
pid_t pids[MAXCMDS];
fprintf(stderr, "%d %s\n", ncmds, cmds[0].cmdargs[0]);
if (1 == ncmds && 0 == strcmp(cmds[0].cmdargs[0], "fg"))
{
if (0 == k)
{
fprintf(stderr, "k == 0\n");
continue;
}
int num = -1;
signal(SIGTTOU, SIG_IGN);
if (0 == cmds[0].cmdargs[1])
{
num = k - 1;
}
else
{
num = atoi(cmds[0].cmdargs[1]);
}
fprintf(stderr, "%d\n", bkgrnds[num]);
if(-1 == tcsetpgrp(STDIN_FILENO, bkgrnds[num]))
{
perror("Couldn't set terminal foreground process group");
return EXIT_FAILURE;
}
signal(SIGTTOU, SIG_DFL);
my_wait(bkgrnds[num], bkgrnds);
signal(SIGTTOU, SIG_IGN);
if (-1 == tcsetpgrp(STDIN_FILENO, getpgrp()))
{
perror("Couldn't set terminal foreground process group");
return EXIT_FAILURE;
}
signal(SIGTTOU, SIG_DFL);
continue;
}
for (i = 0; i < ncmds; i++)
{
int pipefd[2] = {-1, -1};
if(cmds[i].cmdflag & OUTPIP)
{
if(-1 == pipe(pipefd))
{
perror("Couldn't create pipe");
return EXIT_FAILURE;
}
}
{
/* FORK AND EXECUTE */
pids[i] = fork();
if (0 == pids[i])
{
signal(SIGINT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
if(-1 == setpgid(0, (cmds[i].cmdflag & INPIP)? pids[pipeline_start]:0))
{
perror("Couldn't set process group ID");
return EXIT_FAILURE;
}
if (!bkgrnd && !(cmds[i].cmdflag & INPIP))
{
signal(SIGTTOU, SIG_IGN);
if(-1 == tcsetpgrp(STDIN_FILENO, getpgrp()))
{
perror("Couldn't set terminal foreground process group");
return EXIT_FAILURE;
}
signal(SIGTTOU, SIG_DFL);
}
//....
execvp(cmds[i].cmdargs[0], cmds[i].cmdargs);
perror("Couldn't execute command");
return EXIT_FAILURE;
}
else if (-1 != pids[i])
{
if (!bkgrnd)
{
if (!(cmds[i].cmdflag & OUTPIP))
{
{
int j = 0;
for (j = pipeline_start; j <= i; j++)
{
my_wait(pids[j], bkgrnds);
}
}
signal(SIGTTOU, SIG_IGN);
if (-1 == tcsetpgrp(STDIN_FILENO, getpgrp()))
{
perror("Couldn't set terminal foreground process group");
return EXIT_FAILURE;
}
signal(SIGTTOU, SIG_DFL);
}
}
else
{
printf("Background process ID: %ld\n", (long)pids[i]);
}
}
else
{
perror("Couldn't create process");
}
}
}
}
} /* close while */
return EXIT_SUCCESS;
}
static void my_wait(pid_t pid, pid_t bkgrnds[])
{
int status = 0;
if (-1 != waitpid(pid, &status, WUNTRACED))
{
if (WIFSTOPPED(status) && (SIGTSTP == WSTOPSIG(status)))
{
bkgrnds[k++] = pid;
//printf("%d %d\n", pid, k);
kill(pid, SIGCONT);
bkgrnd = 1;
printf("Background process ID: %ld\n", (long)pid);
}
}
else
{
perror("Couldn't wait for child process termination");
}
}
Now I want to implement a command fg.
if (1 == ncmds && 0 == strcmp(cmds[0].cmdargs[0], "fg"))
{
if (0 == k)
{
fprintf(stderr, "k == 0\n");
continue;
}
int num = -1;
signal(SIGTTOU, SIG_IGN);
if (0 == cmds[0].cmdargs[1])
{
num = k - 1;
}
else
{
num = atoi(cmds[0].cmdargs[1]);
}
fprintf(stderr, "%d\n", bkgrnds[num]);
if(-1 == tcsetpgrp(STDIN_FILENO, bkgrnds[num]))
{
perror("Couldn't set terminal foreground process group");
return EXIT_FAILURE;
}
signal(SIGTTOU, SIG_DFL);
my_wait(bkgrnds[num], bkgrnds);
signal(SIGTTOU, SIG_IGN);
if (-1 == tcsetpgrp(STDIN_FILENO, getpgrp()))
{
perror("Couldn't set terminal foreground process group");
return EXIT_FAILURE;
}
signal(SIGTTOU, SIG_DFL);
continue;
}
Question : PID I know how do I bring to the foreground?
That is if I import
cat
CTRL + Z
fg
<- here shall continue cat
Thanks in advance.
Sorry. I just forgot to send SIGCONT process and everything. Added and working. kill(bkgrnds[num], SIGCONT);

Resources