#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/fault.h>
#include <sys/syscall.h>
#include <procfs.h>
#include <sys/auxv.h>
#include <libelf.h>
#include <sys/param.h>
#include <sys/machelf.h>
#include <stdarg.h>
#include <proc_service.h>
#include "rdb.h"
#include "disasm.h"
#include "gram.h"
#define PROCSIZE 20
static void
init_proc()
{
int pfd;
char procname[PROCSIZE];
sigset_t sigset;
fltset_t fltset;
sysset_t sysset;
long oper, pflags;
struct iovec piov[2];
(void) snprintf(procname, PROCSIZE, "/proc/%d/ctl", EC_SWORD(getpid()));
if ((pfd = open(procname, O_WRONLY)) < 0) {
(void) fprintf(stderr, "can't open %s\n", procname);
exit(1);
}
oper = PCSET;
piov[0].iov_base = (caddr_t)(&oper);
piov[0].iov_len = sizeof (oper);
pflags = PR_FORK;
piov[1].iov_base = (caddr_t)&pflags;
piov[1].iov_len = sizeof (pflags);
if (writev(pfd, piov, 2) == -1)
perr("init_proc: PCSET");
oper = PCSTRACE;
premptyset(&sigset);
piov[1].iov_base = (caddr_t)&sigset;
piov[1].iov_len = sizeof (sigset);
if (writev(pfd, piov, 2) == -1)
perr("PCSTRACE");
oper = PCSFAULT;
premptyset(&fltset);
piov[1].iov_base = (caddr_t)&fltset;
piov[1].iov_len = sizeof (fltset);
if (writev(pfd, piov, 2) == -1)
perr("PCSFAULT");
oper = PCSENTRY;
premptyset(&sysset);
piov[1].iov_base = (caddr_t)&sysset;
piov[1].iov_len = sizeof (sysset);
if (writev(pfd, piov, 2) == -1)
perr("PSENTRY");
oper = PCSEXIT;
premptyset(&sysset);
praddset(&sysset, SYS_execve);
if (writev(pfd, piov, 2) == -1)
perr("PCSEXIT");
(void) close(pfd);
}
int
main(int argc, char *argv[])
{
int pctlfd;
int pstatusfd;
char procname[PROCSIZE];
char *command;
char *rdb_commands = NULL;
pid_t cpid;
pstatus_t pstatus;
sysset_t sysset;
int c;
int error = 0;
long oper;
struct iovec piov[2];
extern FILE *yyin;
command = argv[0];
while ((c = getopt(argc, argv, "f:")) != EOF)
switch (c) {
case 'f':
rdb_commands = optarg;
break;
case '?':
break;
}
if (error || (optind == argc)) {
(void) printf("usage: %s [-f file] executable "
"[executable arguments ...]\n", command);
(void) printf("\t-f command file\n");
exit(1);
}
init_proc();
if ((cpid = fork()) == 0) {
(void) execv(argv[optind], &argv[optind]);
perr(argv[optind]);
}
if (cpid == -1)
perr(command);
if (elf_version(EV_CURRENT) == EV_NONE) {
(void) fprintf(stderr, "elf_version() failed: %s\n",
elf_errmsg(0));
exit(1);
}
if (rd_init(RD_VERSION) != RD_OK) {
(void) fprintf(stderr, "librtld_db::rd_init() failed: version "
"submitted: %d\n", RD_VERSION);
exit(1);
}
(void) snprintf(procname, PROCSIZE, "/proc/%d/ctl", EC_SWORD(cpid));
(void) printf("parent: %d child: %d child procname: %s\n",
EC_SWORD(getpid()), EC_SWORD(cpid), procname);
if ((pctlfd = open(procname, O_WRONLY)) < 0) {
perror(procname);
(void) fprintf(stderr, "%s: can't open child %s\n",
command, procname);
exit(1);
}
oper = PCWSTOP;
piov[0].iov_base = (caddr_t)&oper;
piov[0].iov_len = sizeof (oper);
if (writev(pctlfd, piov, 1) == -1)
perr("PCWSTOP");
(void) snprintf(procname, PROCSIZE, "/proc/%d/status", EC_SWORD(cpid));
if ((pstatusfd = open(procname, O_RDONLY)) == -1)
perr(procname);
if (read(pstatusfd, &pstatus, sizeof (pstatus)) == -1)
perr("status read failed");
while ((pstatus.pr_lwp.pr_why == PR_SYSEXIT) &&
(pstatus.pr_lwp.pr_what == SYS_execve)) {
long pflags = 0;
if (!(pstatus.pr_lwp.pr_reg[R_PS] & ERRBIT)) {
break;
}
oper = PCRUN;
piov[1].iov_base = (caddr_t)&pflags;
piov[1].iov_len = sizeof (pflags);
if (writev(pctlfd, piov, 2) == -1)
perr("PCRUN1");
oper = PCWSTOP;
if (writev(pctlfd, piov, 1) == -1)
perr("PCWSTOP");
if (read(pstatusfd, &pstatus, sizeof (pstatus)) == -1)
perr("status read failed");
}
premptyset(&sysset);
oper = PCSEXIT;
piov[1].iov_base = (caddr_t)&sysset;
piov[1].iov_len = sizeof (sysset);
if (writev(pctlfd, piov, 2) == -1)
perr("PIOCSEXIT");
if ((pstatus.pr_lwp.pr_why != PR_SYSEXIT) ||
(pstatus.pr_lwp.pr_what != SYS_execve)) {
long pflags = 0;
(void) fprintf(stderr, "Didn't catch the exec, why: %d "
"what: %d\n", pstatus.pr_lwp.pr_why,
pstatus.pr_lwp.pr_what);
oper = PCRUN;
piov[1].iov_base = (caddr_t)&pflags;
piov[1].iov_len = sizeof (pflags);
if (writev(pctlfd, piov, 2) == -1)
perr("PCRUN2");
exit(1);
}
(void) ps_init(pctlfd, pstatusfd, cpid, &proch);
if (rdb_commands) {
if ((yyin = fopen(rdb_commands, "r")) == NULL) {
(void) printf("unable to open %s for input\n",
rdb_commands);
perr("fopen");
}
} else {
proch.pp_flags |= FLG_PP_PROMPT;
rdb_prompt();
}
(void) yyparse();
if (proch.pp_flags & FLG_PP_PACT) {
long pflags = PRCFAULT;
(void) printf("\ncontinuing the hung process...\n");
pctlfd = proch.pp_ctlfd;
(void) ps_close(&proch);
oper = PCRUN;
piov[1].iov_base = (caddr_t)&pflags;
piov[1].iov_len = sizeof (pflags);
if (writev(pctlfd, piov, 2) == -1)
perr("PCRUN2");
(void) close(pctlfd);
}
return (0);
}