/********************************************
files_children.c
libmawk changes (C) 2009-2014, Tibor 'Igor2' Palinkas;
based on mawk code coming with the below copyright:
copyright 1991-94. Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
#include "conf.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "mawk.h"
#include "files.h"
#include "memory.h"
#include "fin.h"
static void add_to_child_list(mawk_state_t *, int, int);
static struct child *remove_from_child_list(mawk_state_t *, int);
/* we need to wait for children at the end of output pipes to
complete so we know any files they have created are complete */
static void add_to_child_list(mawk_state_t *MAWK, int pid, int exit_status)
{
register struct child *p = MAWK_ZMALLOC(MAWK, struct child);
p->pid = pid;
p->exit_status = exit_status;
p->link = MAWK->child_list;
MAWK->child_list = p;
}
static struct child *remove_from_child_list(mawk_state_t *MAWK, int pid)
{
struct child dummy;
register struct child *p;
struct child *q = &dummy;
dummy.link = p = MAWK->child_list;
while (p) {
if (p->pid == pid) {
q->link = p->link;
break;
}
else {
q = p;
p = p->link;
}
}
MAWK->child_list = dummy.link;
return p;
/* null return if not in the list */
}
#ifndef MAWK_NO_FORK
/* wait for a specific child to complete and return its
exit status
If pid is zero, wait for any single child and
put it on the dead children list
*/
int mawk_wait_for(mawk_state_t *MAWK, int pid)
{
int exit_status;
struct child *p;
int id;
if (pid == 0) {
id = wait(&exit_status);
add_to_child_list(MAWK, id, exit_status);
}
/* see if an earlier wait() caught our child */
else if ((p = remove_from_child_list(MAWK, pid))) {
exit_status = p->exit_status;
MAWK_ZFREE(MAWK, p);
}
else {
/* need to really wait */
while ((id = wait(&exit_status)) != pid) {
if (id == -1) /* can't happen */
mawk_bozo(MAWK, "mawk_wait_for");
else {
/* we got the exit status of another child
put it on the child list and try again */
add_to_child_list(MAWK, id, exit_status);
}
}
}
if (exit_status & 0xff)
exit_status = 128 + (exit_status & 0xff);
else
exit_status = (exit_status & 0xff00) >> 8;
return exit_status;
}
#endif