source: trunk/minix/lib/ip/rcmd.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 6.1 KB
Line 
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#if defined(LIBC_SCCS) && !defined(lint)
21static char sccsid[] = "@(#)rcmd.c 5.22 (Berkeley) 6/1/90";
22#endif /* LIBC_SCCS and not lint */
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <sys/ioctl.h>
27#include <ctype.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <limits.h>
31#include <pwd.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <signal.h>
35#include <string.h>
36#include <unistd.h>
37#include <net/gen/netdb.h>
38#include <net/gen/in.h>
39#include <net/gen/tcp.h>
40#include <net/gen/tcp_io.h>
41#include <net/hton.h>
42#include <net/netlib.h>
43
44#define MAXHOSTNAMELEN 256
45#define MAXPATHLEN PATH_MAX
46
47#ifdef __STDC__
48#define CONST const
49#else
50#define CONST
51#endif
52
53extern errno;
54
55int rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
56char **ahost;
57int rport;
58CONST char *locuser, *remuser, *cmd;
59int *fd2p;
60{
61 int fd, fd2, result;
62 struct hostent *hp;
63 int n;
64 static tcpport_t lport;
65 nwio_tcpconf_t tcpconf;
66 nwio_tcpcl_t tcpconnopt;
67 pid_t pid;
68 char num[8];
69 char c;
70 char *tcp_device;
71
72 fd= -1;
73 fd2= -1;
74
75 if (lport == 0) {
76 pid = getpid();
77 lport = 1;
78 do {
79 lport = (lport << 1) | (pid & 1);
80
81 pid >>= 1;
82 } while (lport < TCPPORT_RESERVED/2);
83 }
84
85 tcp_device= getenv("TCP_DEVICE");
86 if (tcp_device == NULL)
87 tcp_device= TCP_DEVICE;
88 hp= gethostbyname(*ahost);
89 if (!hp)
90 {
91 fprintf(stderr, "%s: unknown host\n", *ahost);
92 return -1;
93 }
94 *ahost= hp->h_name;
95 n = TCPPORT_RESERVED/2;
96 do
97 {
98 if (--lport < TCPPORT_RESERVED/2)
99 lport = TCPPORT_RESERVED-1;
100 fd= open (tcp_device, O_RDWR);
101 if (fd<0)
102 {
103 fprintf(stderr, "unable to open %s: %s\n",
104 tcp_device, strerror(errno));
105 goto bad;
106 }
107 tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_SET_RA | NWTC_SET_RP |
108 NWTC_EXCL;
109 tcpconf.nwtc_locport= htons(lport);
110 tcpconf.nwtc_remport= rport;
111 tcpconf.nwtc_remaddr= *(ipaddr_t *)hp->h_addr;
112
113 result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
114 if (result<0)
115 {
116 if (errno == EADDRINUSE)
117 {
118 close(fd);
119 continue;
120 }
121 fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
122 strerror(errno));
123 goto bad;
124 }
125 tcpconf.nwtc_flags= NWTC_SHARED;
126 result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
127 if (result<0)
128 {
129 fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
130 strerror(errno));
131 goto bad;
132 }
133 tcpconnopt.nwtcl_flags= 0;
134
135 do
136 {
137 result= ioctl (fd, NWIOTCPCONN, &tcpconnopt);
138 if (result<0 && errno == EAGAIN)
139 {
140 sleep(2);
141 }
142 } while (result<0 && errno == EAGAIN);
143 if (result<0 && errno != EADDRINUSE)
144 {
145 fprintf(stderr,
146 "unable to ioctl(NWIOTCPCONN): %s\n",
147 strerror(errno));
148 goto bad;
149 }
150 if (result>=0)
151 break;
152 } while (--n > 0);
153 if (n == 0)
154 {
155 fprintf(stderr, "can't get port\n");
156 return -1;
157 }
158 if (!fd2p)
159 {
160 if (write(fd, "", 1) != 1)
161 {
162 fprintf(stderr, "unable to write: %s", strerror(errno));
163 goto bad;
164 }
165 }
166 else
167 {
168 fd2= open (tcp_device, O_RDWR);
169 if (fd2<0)
170 {
171 fprintf(stderr, "unable to open %s: %s\n",
172 tcp_device, strerror(errno));
173 goto bad;
174 }
175 tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA |
176 NWTC_UNSET_RP | NWTC_SHARED;
177 tcpconf.nwtc_locport= htons(lport);
178
179 result= ioctl(fd2, NWIOSTCPCONF, &tcpconf);
180 if (result<0)
181 {
182 fprintf(stderr,
183 "unable to ioctl(NWIOSTCPCONF): %s\n",
184 strerror(errno));
185 goto bad;
186 }
187 pid= fork();
188 if (pid<0)
189 {
190 fprintf(stderr, "unable to fork: %s\n",
191 strerror(errno));
192 goto bad;
193 }
194 if (!pid)
195 {
196 alarm(0);
197 signal(SIGALRM, SIG_DFL);
198 alarm(30); /* give up after half a minute */
199 tcpconnopt.nwtcl_flags= 0;
200
201 do
202 {
203 result= ioctl (fd2, NWIOTCPLISTEN,
204 &tcpconnopt);
205 if (result<0 && errno == EAGAIN)
206 {
207 sleep(2);
208 }
209 } while (result<0 && errno == EAGAIN);
210 if (result<0 && errno != EADDRINUSE)
211 {
212 fprintf(stderr,
213 "unable to ioctl(NWIOTCPLISTEN): %s\n",
214 strerror(errno));
215 exit(1);
216 }
217 if (result>=0)
218 exit(0);
219 else
220 exit(1);
221 }
222 /*
223 * This sleep is a HACK. The command that we are starting
224 * will try to connect to the fd2 port. It seems that for
225 * this to succeed the child process must have already made
226 * the call to ioctl above (the NWIOTCPLISTEN) call.
227 * The sleep gives the child a chance to make the call
228 * before the parent sends the port number to the
229 * command being started.
230 */
231 sleep(1);
232
233 sprintf(num, "%d", lport);
234 if (write(fd, num, strlen(num)+1) != strlen(num)+1)
235 {
236 fprintf(stderr, "unable to write: %s\n",
237 strerror(errno));
238 goto bad;
239 }
240
241 }
242 write (fd, locuser, strlen(locuser)+1);
243 write (fd, remuser, strlen(remuser)+1);
244 write (fd, cmd, strlen(cmd)+1);
245 if (read(fd, &c, 1) != 1)
246 {
247 fprintf(stderr, "unable to read: %s\n", strerror(errno) );
248 goto bad;
249 }
250 if (c != 0)
251 {
252 while (read(fd, &c, 1) == 1)
253 {
254 write(2, &c, 1);
255 if (c == '\n')
256 break;
257 }
258 goto bad;
259 }
260 if (fd2p)
261 {
262 *fd2p= fd2;
263 result= ioctl(fd2, NWIOGTCPCONF, &tcpconf);
264 if (result<0)
265 {
266 fprintf(stderr, "unable to ioctl(NWIOGTCPCONF): %s\n",
267 strerror(errno) );
268 goto bad;
269 }
270 if (ntohs(tcpconf.nwtc_remport) >= TCPPORT_RESERVED)
271 {
272 fprintf(stderr, "unable to setup 2nd channel\n");
273 goto bad;
274 }
275 }
276 return fd;
277
278bad:
279 if (fd>=0)
280 close(fd);
281 if (fd2>=0)
282 close(fd2);
283 return -1;
284}
Note: See TracBrowser for help on using the repository browser.