23 |
#include <fcntl.h> |
#include <fcntl.h> |
24 |
#include <hurd/trivfs.h> |
#include <hurd/trivfs.h> |
25 |
#include <stdio.h> |
#include <stdio.h> |
26 |
|
#include <argp.h> |
27 |
#include <hurd/fsys.h> |
#include <hurd/fsys.h> |
28 |
#include <string.h> |
#include <string.h> |
29 |
|
|
30 |
|
#include <version.h> |
31 |
|
|
32 |
|
const char *argp_program_version = STANDARD_HURD_VERSION (term); |
33 |
|
|
34 |
int trivfs_fstype = FSTYPE_TERM; |
int trivfs_fstype = FSTYPE_TERM; |
35 |
int trivfs_fsid = 0; /* pid?? */ |
int trivfs_fsid = 0; |
36 |
int trivfs_support_read = 1; |
int trivfs_support_read = 1; |
37 |
int trivfs_support_write = 1; |
int trivfs_support_write = 1; |
38 |
int trivfs_support_exec = 0; |
int trivfs_support_exec = 0; |
39 |
|
|
40 |
int trivfs_allow_open = O_READ|O_WRITE; |
int trivfs_allow_open = O_READ|O_WRITE; |
41 |
|
|
42 |
|
/* The argument line options. */ |
43 |
|
char *tty_name; |
44 |
|
enum { T_NONE = 0, T_DEVICE, T_PTYMASTER, T_PTYSLAVE } tty_type; |
45 |
|
char *tty_arg; |
46 |
|
|
47 |
int |
int |
48 |
demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) |
demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) |
49 |
{ |
{ |
57 |
|| device_reply_server (inp, outp)); |
|| device_reply_server (inp, outp)); |
58 |
} |
} |
59 |
|
|
60 |
|
|
61 |
|
static error_t |
62 |
|
parse_opt (int opt, char *arg, struct argp_state *state) |
63 |
|
{ |
64 |
|
switch (opt) |
65 |
|
{ |
66 |
|
default: |
67 |
|
return ARGP_ERR_UNKNOWN; |
68 |
|
case ARGP_KEY_INIT: |
69 |
|
case ARGP_KEY_SUCCESS: |
70 |
|
case ARGP_KEY_ERROR: |
71 |
|
break; |
72 |
|
case ARGP_KEY_ARG: |
73 |
|
if (!tty_name) |
74 |
|
tty_name = arg; |
75 |
|
else if (!tty_type) |
76 |
|
{ |
77 |
|
if (!strcmp (arg, "device")) |
78 |
|
tty_type = T_DEVICE; |
79 |
|
else if (!strcmp (arg, "pty-master")) |
80 |
|
tty_type = T_PTYMASTER; |
81 |
|
else if (!strcmp (arg, "pty-slave")) |
82 |
|
tty_type = T_PTYSLAVE; |
83 |
|
else |
84 |
|
argp_error (state, "Invalid terminal type"); |
85 |
|
} |
86 |
|
else if (!tty_arg) |
87 |
|
tty_arg = arg; |
88 |
|
else |
89 |
|
argp_error (state, "Too many arguments"); |
90 |
|
break; |
91 |
|
case ARGP_KEY_END: |
92 |
|
if (!tty_name || !tty_type || !tty_arg) |
93 |
|
argp_error (state, "Too few arguments"); |
94 |
|
break; |
95 |
|
} |
96 |
|
return 0; |
97 |
|
} |
98 |
|
|
99 |
|
static struct argp term_argp = |
100 |
|
{ 0, parse_opt, "NAME TYPE ARG", "A translator that emulates a terminal.\v"\ |
101 |
|
"Possible values for TYPE:\n"\ |
102 |
|
" device Use Mach device ARG as bottom handler.\n"\ |
103 |
|
" pty-master Master for slave at ARG.\n"\ |
104 |
|
" pty-slave Slave for master at ARG.\n"\ |
105 |
|
"\n"\ |
106 |
|
"The filename of the node that the translator is attached to should be\n"\ |
107 |
|
"supplied in NAME.\n" }; |
108 |
|
|
109 |
int |
int |
110 |
main (int argc, char **argv) |
main (int argc, char **argv) |
111 |
{ |
{ |
113 |
struct port_class *peerclass, *peercntlclass; |
struct port_class *peerclass, *peercntlclass; |
114 |
struct trivfs_control **ourcntl, **peercntl; |
struct trivfs_control **ourcntl, **peercntl; |
115 |
mach_port_t bootstrap, right; |
mach_port_t bootstrap, right; |
|
enum {T_DEVICE, T_PTYMASTER, T_PTYSLAVE} type; |
|
116 |
struct stat st; |
struct stat st; |
117 |
|
|
118 |
term_bucket = ports_create_bucket (); |
term_bucket = ports_create_bucket (); |
126 |
|
|
127 |
init_users (); |
init_users (); |
128 |
|
|
129 |
task_get_bootstrap_port (mach_task_self (), &bootstrap); |
argp_parse (&term_argp, argc, argv, 0, 0, 0); |
|
|
|
|
if (argc != 4) |
|
|
{ |
|
|
fprintf (stderr, "Usage: term ttyname type arg\n"); |
|
|
exit (1); |
|
|
} |
|
130 |
|
|
131 |
if (!strcmp (argv[2], "device")) |
switch (tty_type) |
132 |
{ |
{ |
133 |
type = T_DEVICE; |
case T_DEVICE: |
134 |
bottom = &devio_bottom; |
bottom = &devio_bottom; |
135 |
ourclass = tty_class; |
ourclass = tty_class; |
136 |
ourcntlclass = tty_cntl_class; |
ourcntlclass = tty_cntl_class; |
138 |
peerclass = 0; |
peerclass = 0; |
139 |
peercntlclass = 0; |
peercntlclass = 0; |
140 |
peercntl = 0; |
peercntl = 0; |
141 |
pterm_name = argv[3]; |
break; |
142 |
} |
|
143 |
else if (!strcmp (argv[2], "pty-master")) |
case T_PTYMASTER: |
|
{ |
|
|
type = T_PTYMASTER; |
|
144 |
bottom = &ptyio_bottom; |
bottom = &ptyio_bottom; |
145 |
ourclass = pty_class; |
ourclass = pty_class; |
146 |
ourcntlclass = pty_cntl_class; |
ourcntlclass = pty_cntl_class; |
148 |
peerclass = tty_class; |
peerclass = tty_class; |
149 |
peercntlclass = tty_cntl_class; |
peercntlclass = tty_cntl_class; |
150 |
peercntl = &termctl; |
peercntl = &termctl; |
151 |
} |
break; |
152 |
else if (!strcmp (argv[2], "pty-slave")) |
|
153 |
{ |
case T_PTYSLAVE: |
|
type = T_PTYSLAVE; |
|
154 |
bottom = &ptyio_bottom; |
bottom = &ptyio_bottom; |
155 |
ourclass = tty_class; |
ourclass = tty_class; |
156 |
ourcntlclass = tty_cntl_class; |
ourcntlclass = tty_cntl_class; |
158 |
peerclass = pty_class; |
peerclass = pty_class; |
159 |
peercntlclass = pty_cntl_class; |
peercntlclass = pty_cntl_class; |
160 |
peercntl = &ptyctl; |
peercntl = &ptyctl; |
161 |
} |
break; |
162 |
else |
|
163 |
{ |
default: |
164 |
fprintf (stderr, |
/* Should not happen. */ |
165 |
"Allowable types are device, pty-master, and pty-slave.\n"); |
fprintf (stderr, "Unknown terminal type is unknown.\n"); |
166 |
exit (1); |
exit (1); |
167 |
} |
} |
168 |
|
|
169 |
|
task_get_bootstrap_port (mach_task_self (), &bootstrap); |
170 |
|
|
171 |
if (bootstrap == MACH_PORT_NULL) |
if (bootstrap == MACH_PORT_NULL) |
172 |
{ |
{ |
173 |
fprintf (stderr, "Must be started as a translator\n"); |
fprintf (stderr, "Must be started as a translator\n"); |
186 |
|
|
187 |
/* For ptys, the nodename depends on which half is used. For now just use |
/* For ptys, the nodename depends on which half is used. For now just use |
188 |
the hook to store the nodename. */ |
the hook to store the nodename. */ |
189 |
(*ourcntl)->hook = argv[1]; |
(*ourcntl)->hook = tty_name; |
190 |
|
|
191 |
/* Set peer */ |
/* Set peer */ |
192 |
if (peerclass) |
if (peerclass) |
193 |
{ |
{ |
194 |
char *peer_name = argv[3]; |
char *peer_name = tty_arg; |
195 |
file_t file = file_name_lookup (peer_name, O_CREAT|O_NOTRANS, 0666); |
file_t file = file_name_lookup (peer_name, O_CREAT|O_NOTRANS, 0666); |
196 |
|
|
197 |
if (file != MACH_PORT_NULL) |
if (file != MACH_PORT_NULL) |