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

Last change on this file since 2906 was 2906, checked in by Pascal Terjan, 13 years ago
  • Cleanup my term after a grab
  • 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
29#if defined HAVE_LINUX_KDEV_T_H
30#   include <linux/kdev_t.h>
31#   include <linux/major.h>
32#endif
33
34#include "neercs.h"
35#include "mytrace.h"
36
37int grab_process(long pid, char *ptyname, int ptyfd)
38{
39#if defined HAVE_LINUX_KDEV_T_H
40    char fdstr[1024];
41    struct mytrace *parent, *child;
42    int i, fd = 0, ret;
43    char to_open[3];
44    int mode[3];
45    struct stat stat_buf;
46    struct termios tos;
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    mytrace_write(parent, 1, "\x1b[H\x1b[2J", 7);
59    mytrace_write(parent, 1, "\n[Process stolen by neercs]\n", 28);
60    mytrace_tcgets(parent, 1, &tos);
61    tos.c_lflag |= ICANON|ECHO;
62    mytrace_tcsets(parent, 1, &tos);
63    mytrace_close(parent, 1);
64    mytrace_exit(parent, 0);
65    mytrace_detach(parent);
66    pid = mytrace_getpid(child);
67
68    /* Look for file descriptors that are PTYs */
69    for(i = 0; i <= 2; i++)
70    {
71        snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%d", pid, i);
72        to_open[i] = 0;
73        lstat(fdstr, &stat_buf);
74        if((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR))
75            mode[i] = O_RDWR;
76        else if(stat_buf.st_mode & S_IWUSR)
77            mode[i] = O_WRONLY;
78        else
79            mode[i] = O_RDONLY;
80
81        if(stat(fdstr, &stat_buf) < 0)
82            continue;
83
84        if(!S_ISCHR(stat_buf.st_mode)
85            || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR)
86            continue;
87
88        debug("found pty %d for pid %d", i, pid);
89
90        ret = mytrace_close(child, i);
91        if(ret < 0)
92        {
93            perror("mytrace_close");
94        }
95        to_open[i] = 1;
96    }
97
98    /* Set the process's session ID */
99    debug("Running setsid on process %ld (sid=%d)", pid, getsid(pid));
100
101    ret = mytrace_setpgid(child, 0, getsid(pid));
102    if(ret < 0)
103    {
104        fprintf(stderr, "syscall setpgid failed\n");
105        mytrace_detach(child);
106        return -1;
107    }
108
109    if(ret != 0)
110    {
111        fprintf(stderr, "setpgid returned %d\n", ret);
112        mytrace_detach(child);
113        return -1;
114    }
115
116    ret = mytrace_setsid(child);
117    if(ret < 0)
118    {
119        fprintf(stderr, "syscall setsid failed\n");
120        mytrace_detach(child);
121        return -1;
122    }
123
124    debug("pid %ld has now sid %d", pid, getsid(pid));
125
126    /* Reopen PTY file descriptors */
127    for(i = 0; i <= 2; i++)
128    {
129        if(!to_open[i])
130            continue;
131        fd = mytrace_open(child, ptyname, mode[i]);
132        if(fd < 0)
133        {
134            perror("mytrace_open");
135        }
136        ret = mytrace_dup2(child, fd, i);
137        if(ret < 0)
138        {
139            perror("mytrace_dup2");
140        }
141    }
142
143    kill(pid, SIGWINCH);
144    mytrace_detach(child);
145
146    return 0;
147#else
148    errno = ENOSYS;
149    return -1;
150#endif
151}
152
Note: See TracBrowser for help on using the repository browser.