root/lang/objective-cplusplus/i3/trunk/src/os-windows/fakecygpty.c @ 35128

Revision 35128, 4.9 kB (checked in by saturday06, 4 years ago)

0dso9ifasdjfaiod

Line 
1/*
2 * Fake cygwin pty   --  fakecygpty --
3 *
4 *        Copyright (C) 2005 Kyotaro Horiguchi <horiguti@meaodwy.org>
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either versions 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with fiber, see the file COPYING.  If not, write to the Free
19 * Software Foundation Inc., 59 Temple Place - Suite 330, Boston,
20 * MA 02111-1307, USA.
21 */
22
23/*
24 * HISTORY
25 * -------
26 *
27 *    09 Jun, 2005 : Version 1.0.0 - first release.
28 *    15 Jun, 2005 : Version 1.0.1 - bug fix and change coding style.
29 */
30
31/*
32 * COMPILATION
33 * -------
34 * gcc -o fakecygpty.exe fakecygpty.c
35 *
36 */
37
38#ifndef __CYGWIN__
39/* Interix */
40#define _ALL_SOURCE
41#endif
42
43#include <errno.h>
44#include <fcntl.h>
45#include <signal.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <sys/time.h>
50#include <sys/wait.h>
51#include <termios.h>
52#include <unistd.h>
53
54#define BUFSIZE          1024   /* size of communication buffer */
55
56/* global variables */
57int child_pid;          /* pid of child proces  */
58int masterfd;           /* fd of pty served to child process */
59
60/* Create pty and fork/exec target process */
61/* This function sets child_pid and masterfd */
62void exec_target(char* argv[]) {
63    int fd;
64    int pid;
65
66    masterfd = open ("/dev/ptmx", O_RDWR);
67    if (masterfd < 0) {
68        perror("Cannot open pseudo tty");
69        exit (1);
70    }
71
72    pid = fork ();
73    if (pid < 0) {
74        perror ("Failed to fork");
75        return;
76    }
77
78    if (pid == 0) {
79        int slave;
80
81        setsid();
82
83        slave = open (ptsname (masterfd), O_RDWR);
84        if (slave < 0) {
85            perror ("Failed to open slave fd");
86            exit (1);
87        }
88
89        for (fd = 0 ; fd < 3 ; fd++) {
90            if (slave != fd) {
91                if (dup2 (slave, fd) < 0) {
92                    perror ("Failed to dup2");
93                    exit (1);
94                }
95            }
96            fcntl (fd, F_SETFD, 0);
97        }
98
99        if (slave > 2) {
100            close (slave);
101        }
102
103        execvp (argv[0], argv);
104
105        fprintf (stderr, "Failed to execute \"%s\".", argv[0]);
106        perror ("execvp");
107        exit (1);
108    }
109
110    child_pid = pid;
111
112    return;
113}
114
115struct termios oldtm;
116
117void setup_tty_attributes (void) {
118    struct termios tm;
119
120    if (tcgetattr (masterfd, &tm) == 0) {
121        /* Inhibit echo when executed under emacs/windows environment */
122        if (! isatty (0)) {
123            tm.c_iflag |= IGNCR;
124            tm.c_lflag &= ~ECHO;
125        }
126        tcsetattr (masterfd, TCSANOW, &tm);
127    }
128
129    if (tcgetattr (0, &oldtm) == 0) {
130        tm = oldtm;
131        tm.c_iflag &= ~(ICRNL | IXON | IXOFF);
132        tm.c_iflag |= IGNBRK;
133        tm.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE);
134        tcsetattr (0, TCSANOW, &tm);
135    }
136}
137
138void restore_tty_attributes (void) {
139    tcsetattr (0, TCSANOW, &oldtm);
140}
141
142#ifdef __CYGWIN__
143/* Signal handler for convert SIGINT into ^C on pty */
144/* This seems not able to be done within cygwin POSIX framework */
145#include <windows.h>
146BOOL WINAPI ctrl_handler(DWORD e) {
147    switch (e) {
148    case CTRL_C_EVENT:
149        write (masterfd, "\003", 1);
150        return TRUE;
151
152    case CTRL_CLOSE_EVENT:
153        kill (child_pid, SIGKILL);
154        return FALSE;
155    }
156    return FALSE;
157}
158#endif
159
160int main (int argc, char* argv[]) {
161    fd_set sel, sel0;
162    int status;
163
164    if (argc < 2) {
165        fprintf (stderr, "Unable to get argv[1].\n");
166        exit (1);
167    }
168
169#ifdef __CYGWIN__
170    /* SIGINT and SIGBREAK are indistinctive under cygwin environment. */
171    /* Using Win32API to handle SIGINT.                              */
172    SetConsoleCtrlHandler (ctrl_handler, TRUE);
173#endif
174
175    exec_target (argv + 1);
176
177    setup_tty_attributes ();
178
179    FD_ZERO (&sel0);
180    FD_SET (masterfd, &sel0);
181    FD_SET (0, &sel0);
182
183    /* communication loop */
184    while (1) {
185        char buf[BUFSIZE];
186        int ret;
187
188        sel = sel0;
189        if (select (FD_SETSIZE, &sel, NULL, NULL, NULL) <= 0) {
190            break;
191        }
192
193        if (FD_ISSET (masterfd, &sel)) {
194            ret = read (masterfd, buf, BUFSIZE);
195            if (ret > 0) {
196                write (1, buf, ret);
197            } else {
198                break;
199            }
200        } else if (FD_ISSET (0, &sel)) {
201            ret = read (0, buf, BUFSIZE);
202            if (ret > 0) {
203                write (masterfd, buf, ret);
204            } else {
205                FD_CLR (0, &sel0);
206                close (masterfd);
207            }
208        }
209    }
210
211    restore_tty_attributes ();
212
213    kill (child_pid, SIGKILL);
214    waitpid (child_pid, &status, 0);
215    return status;
216}
217
Note: See TracBrowser for help on using the browser.