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

Last change on this file since 2 was 2, checked in by piso, 18 years ago

Initial checkin.

File size: 4.3 KB
Line 
1/*
2 * jpty.c
3 *
4 * Copyright (C) 2000-2001 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#endif
28
29#include <stdlib.h>
30#include <unistd.h>
31#include <string.h>
32
33#ifndef __CYGWIN__
34static void set_noecho(int fd);
35static void loop(int fdm);
36static int  open_master_pty(char *name, size_t size);
37#endif
38
39int main(int argc, char *argv[]) 
40{
41#ifndef __CYGWIN__
42    char slave_name[20];
43    pid_t pid;
44    int fdm;
45#endif
46    int i = 1;
47
48    if (argc < 2) exit(1);
49
50    /* Check for -cd option. */
51    if (!strcmp("-cd", argv[i]))
52    {
53        /* Next arg is directory to change to. */
54        if (++i < argc)
55        {
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) exit(1);
64
65#ifdef __CYGWIN__
66    setenv("TERM", "dumb", 1);
67    execvp(argv[i], &argv[i]);
68    exit(1); /* Not reached. */
69#else
70
71    fdm = open_master_pty(slave_name, sizeof(slave_name));
72
73    if (fdm < 0) exit(1);
74
75    pid = fork();
76
77    if (pid < 0) exit(1);
78
79    if (pid == 0)
80    { 
81        /* Child process. */
82        int slave;
83
84        close(fdm);
85
86        if (setsid() < 0) exit(1);
87
88        slave = open(slave_name, O_RDWR);
89
90        if (slave < 0) exit(1);
91
92#ifdef __linux__
93        if (ioctl(slave, TIOCSCTTY, NULL) < 0) exit(1);
94#endif
95
96        if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) exit(1);
97
98        if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) exit(1);
99
100        if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) exit(1);
101
102        if (slave > STDERR_FILENO) close(slave);
103
104        set_noecho(STDIN_FILENO);
105
106        putenv("TERM=dumb");
107
108        execvp(argv[i], &argv[i]);
109
110        /* Not reached. */
111        exit(1);
112    }
113
114    /* Parent process. */
115
116    loop(fdm);
117
118    exit(0);
119
120#endif
121}
122
123#ifndef __CYGWIN__
124static void set_noecho(int fd)
125{
126    struct termios t;
127    if (tcgetattr(fd, &t) < 0) exit(1);
128    t.c_lflag &= ~(ECHO | ECHOCTL | ECHOE | ECHOK | ECHOKE | ECHONL | ECHOPRT);
129    t.c_oflag &= ~(ONLCR);
130    if (tcsetattr(fd, TCSANOW, &t) < 0) exit(1);
131}
132
133/* Copy stdin to fdm, copy fdm to stdout. */
134static void loop(int fdm)
135{
136    char buf[1024];
137    fd_set fdset;
138    int done = 0;
139
140    while (!done)
141    {
142        FD_ZERO(&fdset);
143        FD_SET(STDIN_FILENO, &fdset);
144        FD_SET(fdm, &fdset);
145
146        select(fdm + 1, &fdset, NULL, NULL, NULL);
147
148        if (FD_ISSET(fdm, &fdset))
149        {
150            int i = read(fdm, buf, sizeof(buf));
151
152            if (i > 0)
153                write(STDOUT_FILENO, buf, i);
154            else
155                done = 1;
156        }
157
158        if (FD_ISSET(STDIN_FILENO, &fdset))
159        {
160            int i = read(STDIN_FILENO, buf, sizeof(buf));
161
162            if (i > 0)
163                write(fdm, buf, i);
164            else
165                done = 1;
166        }
167    }
168}
169
170static int open_master_pty(char *namebuf, size_t bufsize)
171{ 
172    char pattern[] = "/dev/ptyXX";
173
174    if (bufsize >= sizeof(pattern))
175    {
176        int i, j;
177
178        strcpy(namebuf, pattern);
179
180        for (i = 0; i < 16; i++)
181        {
182            struct stat statbuf;
183
184            namebuf[8] = "pqrstuvwxyzabcde"[i];
185            namebuf[9] = '0';
186
187            if (stat(namebuf, &statbuf) < 0)
188                continue;
189
190            for (j = 0; j < 16; j++)
191            {
192                int fdm;
193
194                namebuf[9] = "0123456789abcdef"[j];
195
196                fdm = open(namebuf, O_RDWR);
197
198                if (fdm > 0)
199                {
200                    namebuf[5] = 't';
201                    return fdm;
202                }
203            }
204        }
205    }
206
207    return -1;
208}
209#endif
210
Note: See TracBrowser for help on using the repository browser.