Uninitialized vector entry?
[minix3.git] / lib / ip / rcmd.c
blobbc79909ece347fa92038ae36a43e0432ddc8585d
1 /*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
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.
20 #if defined(LIBC_SCCS) && !defined(lint)
21 static char sccsid[] = "@(#)rcmd.c 5.22 (Berkeley) 6/1/90";
22 #endif /* LIBC_SCCS and not lint */
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>
44 #define MAXHOSTNAMELEN 256
45 #define MAXPATHLEN PATH_MAX
47 #ifdef __STDC__
48 #define CONST const
49 #else
50 #define CONST
51 #endif
53 extern errno;
55 int rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
56 char **ahost;
57 int rport;
58 CONST char *locuser, *remuser, *cmd;
59 int *fd2p;
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;
72 fd= -1;
73 fd2= -1;
75 if (lport == 0) {
76 pid = getpid();
77 lport = 1;
78 do {
79 lport = (lport << 1) | (pid & 1);
81 pid >>= 1;
82 } while (lport < TCPPORT_RESERVED/2);
85 tcp_device= getenv("TCP_DEVICE");
86 if (tcp_device == NULL)
87 tcp_device= TCP_DEVICE;
88 hp= gethostbyname(*ahost);
89 if (!hp)
91 fprintf(stderr, "%s: unknown host\n", *ahost);
92 return -1;
94 *ahost= hp->h_name;
95 n = TCPPORT_RESERVED/2;
98 if (--lport < TCPPORT_RESERVED/2)
99 lport = TCPPORT_RESERVED-1;
100 fd= open (tcp_device, O_RDWR);
101 if (fd<0)
103 fprintf(stderr, "unable to open %s: %s\n",
104 tcp_device, strerror(errno));
105 goto bad;
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;
113 result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
114 if (result<0)
116 if (errno == EADDRINUSE)
118 close(fd);
119 continue;
121 fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
122 strerror(errno));
123 goto bad;
125 tcpconf.nwtc_flags= NWTC_SHARED;
126 result= ioctl(fd, NWIOSTCPCONF, &tcpconf);
127 if (result<0)
129 fprintf(stderr, "unable to ioctl(NWIOSTCPCONF): %s\n",
130 strerror(errno));
131 goto bad;
133 tcpconnopt.nwtcl_flags= 0;
137 result= ioctl (fd, NWIOTCPCONN, &tcpconnopt);
138 if (result<0 && errno == EAGAIN)
140 sleep(2);
142 } while (result<0 && errno == EAGAIN);
143 if (result<0 && errno != EADDRINUSE)
145 fprintf(stderr,
146 "unable to ioctl(NWIOTCPCONN): %s\n",
147 strerror(errno));
148 goto bad;
150 if (result>=0)
151 break;
152 } while (--n > 0);
153 if (n == 0)
155 fprintf(stderr, "can't get port\n");
156 return -1;
158 if (!fd2p)
160 if (write(fd, "", 1) != 1)
162 fprintf(stderr, "unable to write: %s", strerror(errno));
163 goto bad;
166 else
168 fd2= open (tcp_device, O_RDWR);
169 if (fd2<0)
171 fprintf(stderr, "unable to open %s: %s\n",
172 tcp_device, strerror(errno));
173 goto bad;
175 tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_UNSET_RA |
176 NWTC_UNSET_RP | NWTC_SHARED;
177 tcpconf.nwtc_locport= htons(lport);
179 result= ioctl(fd2, NWIOSTCPCONF, &tcpconf);
180 if (result<0)
182 fprintf(stderr,
183 "unable to ioctl(NWIOSTCPCONF): %s\n",
184 strerror(errno));
185 goto bad;
187 pid= fork();
188 if (pid<0)
190 fprintf(stderr, "unable to fork: %s\n",
191 strerror(errno));
192 goto bad;
194 if (!pid)
196 alarm(0);
197 signal(SIGALRM, SIG_DFL);
198 alarm(30); /* give up after half a minute */
199 tcpconnopt.nwtcl_flags= 0;
203 result= ioctl (fd2, NWIOTCPLISTEN,
204 &tcpconnopt);
205 if (result<0 && errno == EAGAIN)
207 sleep(2);
209 } while (result<0 && errno == EAGAIN);
210 if (result<0 && errno != EADDRINUSE)
212 fprintf(stderr,
213 "unable to ioctl(NWIOTCPLISTEN): %s\n",
214 strerror(errno));
215 exit(1);
217 if (result>=0)
218 exit(0);
219 else
220 exit(1);
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.
231 sleep(1);
233 sprintf(num, "%d", lport);
234 if (write(fd, num, strlen(num)+1) != strlen(num)+1)
236 fprintf(stderr, "unable to write: %s\n",
237 strerror(errno));
238 goto bad;
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)
247 fprintf(stderr, "unable to read: %s\n", strerror(errno) );
248 goto bad;
250 if (c != 0)
252 while (read(fd, &c, 1) == 1)
254 write(2, &c, 1);
255 if (c == '\n')
256 break;
258 goto bad;
260 if (fd2p)
262 *fd2p= fd2;
263 result= ioctl(fd2, NWIOGTCPCONF, &tcpconf);
264 if (result<0)
266 fprintf(stderr, "unable to ioctl(NWIOGTCPCONF): %s\n",
267 strerror(errno) );
268 goto bad;
270 if (ntohs(tcpconf.nwtc_remport) >= TCPPORT_RESERVED)
272 fprintf(stderr, "unable to setup 2nd channel\n");
273 goto bad;
276 return fd;
278 bad:
279 if (fd>=0)
280 close(fd);
281 if (fd2>=0)
282 close(fd2);
283 return -1;