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

Last change on this file since 2516 was 2516, checked in by sam, 6 years ago
  • Fork the grabbed process and exit the parent. Unfortunately for some reason it still survives as a zombie, there must be something wrong with the setsid/setpgid mechanism we use (maybe setpgrp is needed?).
  • 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    pid = mytrace_getpid(child);
57
58    /* Look for file descriptors that are PTYs */
59    for(i = 0; i <= 2; i++)
60    {
61        snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%d", pid, i);
62        to_open[i] = 0;
63        lstat(fdstr, &stat_buf);
64        if((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR))
65            mode = O_RDWR;
66        else if(stat_buf.st_mode & S_IWUSR)
67            mode = O_WRONLY;
68        else
69            mode = O_RDONLY;
70
71        if(stat(fdstr, &stat_buf) < 0)
72            continue;
73
74        if(!S_ISCHR(stat_buf.st_mode)
75            || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR)
76            continue;
77
78        debug("found pty %d", i);
79
80        if(i == 2)
81        {
82            mytrace_write(parent, i, "\x1b]0;\x07", 5);
83            mytrace_write(parent, i, "\x1b[1000l", 7);
84            mytrace_write(parent, i, "\x1b[?12l\x1b[?25h", 12);
85            mytrace_write(parent, i, "\n[Process stolen by neercs]\n", 28);
86        }
87
88        ret = mytrace_close(child, i);
89        if(ret < 0)
90        {
91            perror("mytrace_close");
92        }
93        to_open[i] = 1;
94    }
95
96    /* Set the process's session ID */
97    debug("Running setsid on process %ld (sid=%d)", pid, getsid(pid));
98
99    ret = mytrace_setpgid(child, 0, getsid(pid));
100    if(ret < 0)
101    {
102        fprintf(stderr, "syscall setpgid failed\n");
103        mytrace_detach(child);
104        return -1;
105    }
106
107    if(ret != 0)
108    {
109        fprintf(stderr, "setpgid returned %d\n", ret);
110        mytrace_detach(child);
111        return -1;
112    }
113
114    ret = mytrace_setsid(child);
115    if(ret < 0)
116    {
117        fprintf(stderr, "syscall setsid failed\n");
118        mytrace_detach(child);
119        return -1;
120    }
121
122    debug("pid %ld has now sid %d", pid, getsid(pid));
123
124    mytrace_exit(parent, 0);
125    mytrace_detach(parent);
126
127    /* Reopen PTY file descriptors */
128    for(i = 0; i <= 2; i++)
129    {
130        if(!to_open[i])
131            continue;
132        fd = mytrace_open(child, ptyname, mode);
133        if(fd < 0)
134        {
135            perror("mytrace_open");
136        }
137        ret = mytrace_dup2(child, fd, i);
138        if(ret < 0)
139        {
140            perror("mytrace_dup2");
141        }
142    }
143
144    kill(pid, SIGWINCH);
145    mytrace_detach(child);
146
147    return 0;
148#else
149    errno = ENOSYS;
150    return -1;
151#endif
152}
153
Note: See TracBrowser for help on using the repository browser.