source: neercs/trunk/src/grab.c @ 3319

Last change on this file since 3319 was 3319, checked in by Pascal Terjan, 12 years ago
  • Wait for reset to exit before displaying nice message
  • Property svn:eol-style set to native
File size: 3.5 KB
Line 
1/*
2 *  neercs        console-based window manager
3 *  Copyright (c) 2008 Pascal Terjan
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This program is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15#include "config.h"
16
17#define _XOPEN_SOURCE 500 /* getsid() */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <errno.h>
22#include <fcntl.h>
23#include <signal.h>
24#include <string.h>
25#include <unistd.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29
30#if defined HAVE_LINUX_KDEV_T_H
31#   include <linux/kdev_t.h>
32#   include <linux/major.h>
33#endif
34
35#include "neercs.h"
36#include "mytrace.h"
37
38int grab_process(long pid, char *ptyname, int ptyfd)
39{
40#if defined HAVE_LINUX_KDEV_T_H
41    char fdstr[1024];
42    struct mytrace *parent, *child;
43    int i, fd = 0, ret;
44    char to_open[3];
45    int mode[3];
46    struct stat stat_buf;
47
48    debug("pty is %s", ptyname);
49
50    parent = mytrace_attach(pid);
51    if(!parent)
52    {
53        fprintf(stderr, "Cannot access process %ld\n", pid);
54        return -1;
55    }
56
57    child = mytrace_fork(parent);
58    ret = mytrace_exec(parent, "/usr/bin/reset");
59    if(ret < 0)
60        mytrace_exit(parent, 0);
61    mytrace_detach(parent);
62    waitpid(pid, NULL, 0); /* Wait for reset to finish before displaying */
63    mytrace_write(child, 1, "\x1b[H\x1b[2J", 7);
64    mytrace_write(child, 1, "\n[Process stolen by neercs]\r\n\n", 30);
65    pid = mytrace_getpid(child);
66
67    /* Look for file descriptors that are PTYs */
68    for(i = 0; i <= 2; i++)
69    {
70        snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%d", pid, i);
71        to_open[i] = 0;
72        lstat(fdstr, &stat_buf);
73        if((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR))
74            mode[i] = O_RDWR;
75        else if(stat_buf.st_mode & S_IWUSR)
76            mode[i] = O_WRONLY;
77        else
78            mode[i] = O_RDONLY;
79
80        if(stat(fdstr, &stat_buf) < 0)
81            continue;
82
83        if(!S_ISCHR(stat_buf.st_mode)
84            || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR)
85            continue;
86
87        debug("found pty %d for pid %d", i, pid);
88
89        ret = mytrace_close(child, i);
90        if(ret < 0)
91        {
92            perror("mytrace_close");
93        }
94        to_open[i] = 1;
95    }
96
97    /* Set the process's session ID */
98    debug("Running setsid on process %ld (sid=%d)", pid, getsid(pid));
99
100    ret = mytrace_setpgid(child, 0, getsid(pid));
101    if(ret < 0)
102    {
103        fprintf(stderr, "syscall setpgid failed\n");
104        mytrace_detach(child);
105        return -1;
106    }
107
108    if(ret != 0)
109    {
110        fprintf(stderr, "setpgid returned %d\n", ret);
111        mytrace_detach(child);
112        return -1;
113    }
114
115    ret = mytrace_setsid(child);
116    if(ret < 0)
117    {
118        fprintf(stderr, "syscall setsid failed\n");
119        mytrace_detach(child);
120        return -1;
121    }
122
123    debug("pid %ld has now sid %d", pid, getsid(pid));
124
125    /* Reopen PTY file descriptors */
126    for(i = 0; i <= 2; i++)
127    {
128        if(!to_open[i])
129            continue;
130        fd = mytrace_open(child, ptyname, mode[i]);
131        if(fd < 0)
132        {
133            perror("mytrace_open");
134        }
135        ret = mytrace_dup2(child, fd, i);
136        if(ret < 0)
137        {
138            perror("mytrace_dup2");
139        }
140    }
141
142    kill(pid, SIGWINCH);
143    mytrace_detach(child);
144
145    return 0;
146#else
147    errno = ENOSYS;
148    return -1;
149#endif
150}
151
Note: See TracBrowser for help on using the repository browser.