#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <stropts.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/termio.h>
#include <libproc.h>
#include "ramdata.h"
#include "proto.h"
void Ecritical(int);
void Xcritical(int);
void
Flush()
{
errno = 0;
Ecritical(0);
(void) fflush(stdout);
Xcritical(0);
if (ferror(stdout) && errno)
interrupt = SIGTERM;
}
void
Eserialize()
{
Ecritical(0);
}
void
Xserialize()
{
(void) fflush(stdout);
Xcritical(0);
}
void
Ecritical(int num)
{
int rv;
if (num == 0)
rv = mutex_lock(&gps->ps_mutex0);
else if (num == 1)
rv = mutex_lock(&gps->ps_mutex1);
else
abend("Invalid mutex specified", NULL);
if (rv != 0) {
char mnum[2];
mnum[0] = '0' + num;
mnum[1] = '\0';
errno = rv;
perror(command);
errmsg("cannot grab mutex #", mnum);
}
}
void
Xcritical(int num)
{
int rv;
if (num == 0)
rv = mutex_unlock(&gps->ps_mutex0);
else if (num == 1)
rv = mutex_unlock(&gps->ps_mutex1);
else
abend("Invalid mutex specified", NULL);
if (rv != 0) {
char mnum[2];
mnum[0] = '0' + num;
mnum[1] = '\0';
errno = rv;
perror(command);
errmsg("cannot release mutex #", mnum);
}
}
void
procadd(pid_t spid, const char *lwplist)
{
int i;
int j = -1;
if (gps == NULL)
return;
Ecritical(1);
for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) {
if (gps->tpid[i] == 0) {
if (j == -1)
j = i;
if (gps->spid[i] == 0)
break;
}
}
if (i < sizeof (gps->tpid) / sizeof (gps->tpid[0]))
j = i;
if (j >= 0) {
gps->tpid[j] = getpid();
gps->spid[j] = spid;
gps->lwps[j] = lwplist;
}
Xcritical(1);
}
void
procdel()
{
int i;
pid_t tpid;
if (gps == NULL)
return;
tpid = getpid();
Ecritical(1);
for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) {
if (gps->tpid[i] == tpid) {
gps->tpid[i] = 0;
break;
}
}
Xcritical(1);
}
int
lwptrace(pid_t spid, lwpid_t lwpid)
{
int i;
pid_t tpid;
const char *lwps;
if (gps == NULL)
return (0);
tpid = getpid();
Ecritical(1);
for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) {
if (gps->tpid[i] == tpid &&
gps->spid[i] == spid)
break;
}
lwps = gps->lwps[i];
Xcritical(1);
return (proc_lwp_in_set(lwps, lwpid));
}
int
checkproc(private_t *pri)
{
char *path = pri->sys_path;
const pstatus_t *Psp = Pstatus(Proc);
struct ps_lwphandle *Lwp = pri->Lwp;
const lwpstatus_t *Lsp = pri->lwpstat;
int what = Lsp->pr_what;
int err = Lsp->pr_errno;
int pid;
int i;
const char *dirname;
char *next;
char *sp1;
char *sp2;
prgreg_t pc;
if ((sp1 = strrchr(path, '/')) == NULL)
;
else if (isdigit(*(sp1+1))) {
sp1 += strlen(sp1);
while (--sp1 > path && isdigit(*sp1))
;
if (*sp1 != '/')
return (0);
} else if (strcmp(sp1+1, "as") == 0 ||
strcmp(sp1+1, "ctl") == 0) {
*sp1 = '\0';
} else if (strcmp(sp1+1, "lwpctl") == 0) {
if (sp1-6 >= path && strncmp(sp1-6, "/agent", 6) == 0)
sp1 -= 6;
else {
while (--sp1 > path && isdigit(*sp1))
;
}
if (*sp1 != '/' ||
(sp1 -= 4) <= path ||
strncmp(sp1, "/lwp", 4) != 0)
return (0);
*sp1 = '\0';
} else if (strcmp(sp1+1, "self") != 0) {
return (0);
}
if ((sp2 = strrchr(path, '/')) == NULL)
dirname = path;
else
dirname = sp2 + 1;
if (strcmp(dirname, "self") == 0) {
pid = Psp->pr_pid;
} else if ((pid = strtol(dirname, &next, 10)) < 0 ||
*next != '\0') {
if (sp1 != NULL)
*sp1 = '/';
return (0);
}
if (sp2 == NULL)
dirname = ".";
else {
*sp2 = '\0';
dirname = path;
}
if (!Pisprocdir(Proc, dirname) ||
pid == getpid() ||
pid == 0) {
if (sp1 != NULL)
*sp1 = '/';
if (sp2 != NULL)
*sp2 = '/';
return (0);
}
if (sp1 != NULL)
*sp1 = '/';
if (sp2 != NULL)
*sp2 = '/';
if (pid == Psp->pr_pid) {
return (1);
}
for (i = 0; i < sizeof (gps->tpid)/sizeof (gps->tpid[0]); i++) {
if (gps->spid[i] == pid) {
pid = gps->tpid[i];
break;
}
}
if (i >= sizeof (gps->tpid) / sizeof (gps->tpid[0])) {
return (0);
}
while (pid && gps->tpid[i] == pid) {
if (kill(pid, SIGUSR1) == -1)
break;
(void) usleep(1000000);
}
Ecritical(1);
if (gps->tpid[i] == 0)
gps->spid[i] = 0;
Xcritical(1);
if (err) {
#if defined(__sparc)
(void) Lgetareg(Lwp, R_PC, &pc);
if (pri->sys_indirect) {
(void) Lputareg(Lwp, R_G1, (prgreg_t)SYS_syscall);
(void) Lputareg(Lwp, R_O0, (prgreg_t)what);
for (i = 0; i < 5; i++)
(void) Lputareg(Lwp, R_O1+i, pri->sys_args[i]);
} else {
(void) Lputareg(Lwp, R_G1, (prgreg_t)what);
for (i = 0; i < 6; i++)
(void) Lputareg(Lwp, R_O0+i, pri->sys_args[i]);
}
(void) Lputareg(Lwp, R_nPC, pc);
#elif defined(__amd64)
(void) Lgetareg(Lwp, R_PC, &pc);
(void) Lputareg(Lwp, REG_RAX, (prgreg_t)what);
#elif defined(__i386)
(void) Lgetareg(Lwp, R_PC, &pc);
(void) Lputareg(Lwp, EAX, (prgreg_t)what);
#else
#error "unrecognized architecture"
#endif
(void) Pissyscall_prev(Proc, pc, (uintptr_t *)&pc);
(void) Lputareg(Lwp, R_PC, pc);
return (2);
}
return (3);
}