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

Last change on this file since 2785 was 2785, checked in by Pascal Terjan, 14 years ago
  • Fix grab to work again on systems using sysenter instead of int 80
  • 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, mode, ret;
43    char to_open[3];
44    struct stat stat_buf;
45
46    debug("pty is %s", ptyname);
47
48    parent = mytrace_attach(pid);
49    if(!parent)
50    {
51        fprintf(stderr, "Cannot access process %ld\n", pid);
52        return -1;
53    }
54
55    child = mytrace_fork(parent);
56    mytrace_write(parent, 1, "\x1b]0;\x07", 5);
57    mytrace_write(parent, 1, "\x1b[1000l", 7);
58    mytrace_write(parent, 1, "\x1b[?12l\x1b[?25h", 12);
59    mytrace_write(parent, 1, "\n[Process stolen by neercs]\n", 28);
60    /* FIXME Reset the term */
61    mytrace_close(parent, 1);
62
63    mytrace_exit(parent, 0);
64    mytrace_detach(parent);
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 = O_RDWR;
75        else if(stat_buf.st_mode & S_IWUSR)
76            mode = O_WRONLY;
77        else
78            mode = 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);
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.