ref: 2aee89298cbbf5c1b4d50e70733b52ae75c706fd
dir: /libnpe/wait.c/
#include <npe.h>
#include <signal.h>
static struct {
char *msg; /* just check prefix */
int num;
} sigtab[] = {
{"interrupt", SIGINT},
{"sys: trap: illegal instruction", SIGILL},
{"sys: trap: reserved instruction", SIGILL},
{"sys: trap: reserved", SIGILL},
{"sys: trap: arithmetic overflow", SIGFPE},
{"abort", SIGABRT},
{"sys: fp:", SIGFPE},
{"exit", SIGKILL},
{"die", SIGKILL},
{"kill", SIGKILL},
{"sys: trap: bus error", SIGSEGV},
{"sys: trap: address error", SIGSEGV},
{"sys: trap: TLB", SIGSEGV},
{"term", SIGTERM},
};
#define NSIGTAB ((sizeof sigtab)/(sizeof (sigtab[0])))
int
_stringsig(char *nam)
{
int i;
for(i = 0; i<NSIGTAB; i++)
if(strncmp(nam, sigtab[i].msg, strlen(sigtab[i].msg)) == 0)
return sigtab[i].num;
return 0;
}
/*
* status not yet collected for processes that have exited
*/
typedef struct Waited Waited;
struct Waited {
Waitmsg* msg;
Waited* next;
};
static Waited *wd;
static Waitmsg *
lookpid(int pid)
{
Waited **wl, *w;
Waitmsg *msg;
for(wl = &wd; (w = *wl) != nil; wl = &w->next)
if(pid <= 0 || w->msg->pid == pid){
msg = w->msg;
*wl = w->next;
free(w);
return msg;
}
return 0;
}
static void
addpid(Waitmsg *msg)
{
Waited *w;
w = malloc(sizeof(*w));
if(w == nil){
/* lost it; what can we do? */
free(msg);
return;
}
w->msg = msg;
w->next = wd;
wd = w;
}
static int
waitstatus(Waitmsg *w)
{
int r, t;
char *bp, *ep;
r = 0;
t = 0;
if(w->msg[0]){
/* message is 'prog pid:string' */
bp = w->msg;
while(*bp){
if(*bp++ == ':')
break;
}
if(*bp == 0)
bp = w->msg;
r = strtol(bp, &ep, 10);
if(*ep == 0){
if(r < 0 || r >= 256)
r = 1;
}else{
t = _stringsig(bp);
if(t == 0)
r = 1;
}
}
return (r<<8) | t;
}
int
npe_waitpid(int wpid, int *status, int options)
{
char pname[50];
Dir *d;
Waitmsg *w;
w = lookpid(wpid);
if(w == nil){
if(options & WNOHANG){
snprintf(pname, sizeof(pname), "/proc/%d/wait", getpid());
d = dirstat(pname);
if(d != nil && d->length == 0){
free(d);
return 0;
}
free(d);
}
for(;;){
w = wait();
if(w == nil){
return -1;
}
if(wpid <= 0 || w->pid == wpid)
break;
addpid(w);
}
}
if(status != nil)
*status = waitstatus(w);
wpid = w->pid;
free(w);
return wpid;
}