#include #include #include #include #include #include #include #include #include #include "util.h" #include "interfere.h" const char *progname="redirectfd"; struct private { int fd; int targetfd; char *filename; }; int redirectfd(struct process *proc, struct private *priv) { PROC_BEGIN(proc); proc_open(proc, priv->filename, O_RDWR|O_CREAT|O_APPEND, 0666); if (proc->last_error) { warn("open(pid %li, file %s): %s\n", (long)proc->pid, priv->filename, strerror(proc->last_error)); goto out; } priv->fd=proc->retval; if (priv->fd != priv->targetfd) { proc_dup2(proc, priv->fd, priv->targetfd); if (proc->last_error) { warn("dup2(pid %li): %s\n", (long)proc->pid, strerror(proc->last_error)); goto out; } } printf("pid %li: Redirected fd %i -> %s\n", (long)proc->pid, priv->targetfd, priv->filename); if (priv->fd != priv->targetfd) { proc_close(proc, priv->fd); if (proc->last_error) { warn("close(pid %li): %s\n", (long)proc->pid, strerror(proc->last_error)); goto out; } } out: PROC_END(proc); } int main(int argc, char *argv[]) { pid_t pid; int status; struct process proc; struct private priv; char cwd[PATH_MAX]; char *filename; if (argc>0) setprogname(argv[0]); if (argc<4) die("Usage: %s pid fd filename\n", progname); pid=str_to_pid(argv[1]); priv.targetfd=str_to_fd(argv[2]); filename=argv[3]; if (filename[0] != '/') { char *newname; if (!getcwd(cwd, sizeof(cwd))) die("getcwd: %s\n", strerror(errno)); if (!strcmp(cwd, "/")) *cwd=0; newname=malloc(strlen(cwd)+1+strlen(filename)+1); if (!newname) die("malloc: %s\n", strerror(errno)); sprintf(newname, "%s/%s", cwd, filename); filename=newname; } priv.filename=filename; if (pid==0) die("Invalid pid: 0\n"); proc_init(&proc); proc_attach(&proc, pid); while (1) { pid=waitpid(proc.pid, &status, 0); if (pid==-1) { if (errno==EINTR) continue; if (errno==ECHILD) break; die("waitpid: %s\n", strerror(errno)); } redirectfd(&proc, &priv); } return 0; }