137 lines
2.9 KiB
C
137 lines
2.9 KiB
C
#define NOPLAN9DEFINES
|
|
#include <u.h>
|
|
#include <libc.h>
|
|
|
|
#include <signal.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
|
|
#ifndef WCOREDUMP /* not on Mac OS X Tiger */
|
|
#define WCOREDUMP(status) 0
|
|
#endif
|
|
|
|
static struct {
|
|
int sig;
|
|
char *str;
|
|
} tab[] = {
|
|
SIGHUP, "hangup",
|
|
SIGINT, "interrupt",
|
|
SIGQUIT, "quit",
|
|
SIGILL, "sys: illegal instruction",
|
|
SIGTRAP, "sys: breakpoint",
|
|
SIGABRT, "sys: abort",
|
|
#ifdef SIGEMT
|
|
SIGEMT, "sys: emulate instruction executed",
|
|
#endif
|
|
SIGFPE, "sys: fp: trap",
|
|
SIGKILL, "sys: kill",
|
|
SIGBUS, "sys: bus error",
|
|
SIGSEGV, "sys: segmentation violation",
|
|
SIGALRM, "alarm",
|
|
SIGTERM, "kill",
|
|
SIGURG, "sys: urgent condition on socket",
|
|
SIGSTOP, "sys: stop",
|
|
SIGTSTP, "sys: tstp",
|
|
SIGCONT, "sys: cont",
|
|
SIGCHLD, "sys: child",
|
|
SIGTTIN, "sys: ttin",
|
|
SIGTTOU, "sys: ttou",
|
|
#ifdef SIGIO /* not on Mac OS X Tiger */
|
|
SIGIO, "sys: i/o possible on fd",
|
|
#endif
|
|
SIGXCPU, "sys: cpu time limit exceeded",
|
|
SIGXFSZ, "sys: file size limit exceeded",
|
|
SIGVTALRM, "sys: virtual time alarm",
|
|
SIGPROF, "sys: profiling timer alarm",
|
|
#ifdef SIGWINCH /* not on Mac OS X Tiger */
|
|
SIGWINCH, "sys: window size change",
|
|
#endif
|
|
#ifdef SIGINFO
|
|
SIGINFO, "sys: status request",
|
|
#endif
|
|
SIGUSR1, "sys: usr1",
|
|
SIGUSR2, "sys: usr2",
|
|
SIGPIPE, "sys: write on closed pipe",
|
|
};
|
|
|
|
char*
|
|
_p9sigstr(int sig, char *tmp)
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<nelem(tab); i++)
|
|
if(tab[i].sig == sig)
|
|
return tab[i].str;
|
|
if(tmp == nil)
|
|
return nil;
|
|
sprint(tmp, "sys: signal %d", sig);
|
|
return tmp;
|
|
}
|
|
|
|
int
|
|
_p9strsig(char *s)
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<nelem(tab); i++)
|
|
if(strcmp(s, tab[i].str) == 0)
|
|
return tab[i].sig;
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
_await(int pid4, char *str, int n, int opt)
|
|
{
|
|
int pid, status, cd;
|
|
struct rusage ru;
|
|
char buf[128], tmp[64];
|
|
uint64_t u, s;
|
|
|
|
for(;;){
|
|
/* On Linux, pid==-1 means anyone; on SunOS, it's pid==0. */
|
|
if(pid4 == -1)
|
|
pid = wait3(&status, opt, &ru);
|
|
else
|
|
pid = wait4(pid4, &status, opt, &ru);
|
|
if(pid <= 0)
|
|
return -1;
|
|
u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
|
|
s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
|
|
if(WIFEXITED(status)){
|
|
status = WEXITSTATUS(status);
|
|
if(status)
|
|
snprint(buf, sizeof buf, "%d %lud %lud %lud %d", pid, u, s, u+s, status);
|
|
else
|
|
snprint(buf, sizeof buf, "%d %lud %lud %lud ''", pid, u, s, u+s, status);
|
|
strecpy(str, str+n, buf);
|
|
return strlen(str);
|
|
}
|
|
if(WIFSIGNALED(status)){
|
|
cd = WCOREDUMP(status);
|
|
snprint(buf, sizeof buf, "%d %lud %lud %lud 'signal: %s%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp), cd ? " (core dumped)" : "");
|
|
strecpy(str, str+n, buf);
|
|
return strlen(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
await(char *str, int n)
|
|
{
|
|
return _await(-1, str, n, 0);
|
|
}
|
|
|
|
int
|
|
awaitnohang(char *str, int n)
|
|
{
|
|
return _await(-1, str, n, WNOHANG);
|
|
}
|
|
|
|
int
|
|
awaitfor(int pid, char *str, int n)
|
|
{
|
|
return _await(pid, str, n, 0);
|
|
}
|