source: trunk/j/src/jpty/jpty.c @ 8076

Last change on this file since 8076 was 8076, checked in by piso, 19 years ago

/dev/ptmx

File size: 3.9 KB
Line 
1/*
2 * jpty.c
3 *
4 * Copyright (C) 2000-2004 Peter Graves
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21#ifndef __CYGWIN__
22#include <fcntl.h>
23#include <grp.h>
24#include <sys/ioctl.h>
25#include <sys/stat.h>
26#include <termios.h>
27#define __USE_XOPEN
28#endif
29
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33
34#ifndef __CYGWIN__
35static void set_noecho(int fd);
36static void loop(int fdm);
37static int  open_master_pty(char *name, size_t size);
38#endif
39
40int main(int argc, char *argv[]) 
41{
42#ifndef __CYGWIN__
43    char slave_name[256];
44    pid_t pid;
45    int fdm;
46#endif
47    int i = 1;
48
49    if (argc < 2)
50  exit(1);
51
52    /* Check for -cd option. */
53    if (!strcmp("-cd", argv[i])) {
54        /* Next arg is directory to change to. */
55        if (++i < argc) {
56            if (chdir(argv[i]) < 0)
57                exit(1);
58            ++i;
59        }
60    }
61
62    /* We should not be out of args here! */
63    if (i >= argc)
64  exit(1);
65
66#ifdef __CYGWIN__
67    setenv("TERM", "dumb", 1);
68    execvp(argv[i], &argv[i]);
69    exit(1); /* Not reached. */
70#else
71    fdm = open_master_pty(slave_name, sizeof(slave_name));
72
73    if (fdm < 0)
74  exit(1);
75
76    pid = fork();
77
78    if (pid < 0)
79  exit(1);
80
81    if (pid == 0) { 
82        /* Child process. */
83        int slave;
84
85        close(fdm);
86
87        if (setsid() < 0)
88      exit(1);
89
90        slave = open(slave_name, O_RDWR);
91
92        if (slave < 0)
93      exit(1);
94
95#ifdef __linux__
96        if (ioctl(slave, TIOCSCTTY, NULL) < 0)
97      exit(1);
98#endif
99        if (dup2(slave, STDIN_FILENO) != STDIN_FILENO)
100      exit(1);
101        if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO)
102      exit(1);
103        if (dup2(slave, STDERR_FILENO) != STDERR_FILENO)
104      exit(1);
105
106        if (slave > STDERR_FILENO)
107      close(slave);
108
109        set_noecho(STDIN_FILENO);
110
111        putenv("TERM=dumb");
112
113        execvp(argv[i], &argv[i]);
114
115        /* Not reached. */
116        exit(1);
117    }
118
119    /* Parent process. */
120    loop(fdm);
121    exit(0);
122#endif
123}
124
125#ifndef __CYGWIN__
126static void set_noecho(int fd)
127{
128    struct termios t;
129    if (tcgetattr(fd, &t) < 0)
130  exit(1);
131    t.c_lflag &= ~(ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
132    t.c_oflag &= ~(ONLCR);
133    if (tcsetattr(fd, TCSANOW, &t) < 0)
134  exit(1);
135}
136
137/* Copy stdin to fdm, copy fdm to stdout. */
138static void loop(int fdm)
139{
140    char buf[1024];
141    fd_set fdset;
142    int done = 0;
143
144    while (!done) {
145        FD_ZERO(&fdset);
146        FD_SET(STDIN_FILENO, &fdset);
147        FD_SET(fdm, &fdset);
148
149        select(fdm + 1, &fdset, NULL, NULL, NULL);
150
151        if (FD_ISSET(fdm, &fdset)) {
152            int i = read(fdm, buf, sizeof(buf));
153
154            if (i > 0)
155                write(STDOUT_FILENO, buf, i);
156            else
157                done = 1;
158        }
159
160        if (FD_ISSET(STDIN_FILENO, &fdset)) {
161            int i = read(STDIN_FILENO, buf, sizeof(buf));
162
163            if (i > 0)
164                write(fdm, buf, i);
165            else
166                done = 1;
167        }
168    }
169}
170
171static int open_master_pty(char *namebuf, size_t bufsize)
172{ 
173    int fdm;
174    char *sname;
175
176    fdm = open("/dev/ptmx", O_RDWR);
177    if (fdm < 0)
178  return -1;
179
180    unlockpt(fdm);
181    grantpt(fdm);
182
183    sname = ptsname(fdm);
184    if (strlen(sname) >= bufsize)
185  return -1;
186    strcpy(namebuf, sname);
187
188    return fdm;
189}
190#endif
Note: See TracBrowser for help on using the repository browser.