4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1999 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
35 #pragma ident "%Z%%M% %I% %E% SMI"
44 #include <sys/types.h>
47 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
58 #define index(s, c) strchr(s, c)
63 char myrcmd_stderr
[1024];
66 myrcmd(char **ahost
, unsigned short rport
, char *locuser
, char *remuser
,
69 uint_t loclen
, remlen
, cmdlen
;
73 struct sockaddr_in sin
;
80 struct sigaction oldaction
;
81 struct sigaction newaction
;
82 static struct hostent numhp
;
83 static char numhostname
[32]; /* big enough for "255.255.255.255" */
84 struct in_addr numaddr
;
85 struct in_addr
*numaddrlist
[2];
87 myrcmd_stderr
[0] = '\0'; /* empty error string */
89 hp
= gethostbyname(*ahost
);
93 bzero((char *)numaddrlist
, sizeof (numaddrlist
));
94 if ((numaddr
.s_addr
= inet_addr(*ahost
)) == (in_addr_t
)-1) {
95 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
96 gettext("%s: unknown host\n"), *ahost
);
97 return (MYRCMD_NOHOST
);
99 bzero((char *)&numhp
, sizeof (numhp
));
100 bzero(numhostname
, sizeof (numhostname
));
102 if ((straddr
= inet_ntoa(numaddr
)) == (char *)0) {
103 (void) snprintf(myrcmd_stderr
,
104 sizeof (myrcmd_stderr
),
105 gettext("%s: unknown host\n"), *ahost
);
106 return (MYRCMD_NOHOST
);
108 (void) strncpy(numhostname
, straddr
,
109 sizeof (numhostname
));
110 numhostname
[sizeof (numhostname
) - 1] = '\0';
111 numhp
.h_name
= numhostname
;
112 numhp
.h_addrtype
= AF_INET
;
113 numhp
.h_length
= sizeof (numaddr
);
114 numaddrlist
[0] = &numaddr
;
115 numaddrlist
[1] = NULL
;
116 numhp
.h_addr_list
= (char **)numaddrlist
;
122 /* This provides a bounds-test for the bcopy()s below. */
123 if ((unsigned)(hp
->h_length
) > sizeof (sin
.sin_addr
)) {
124 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
125 gettext("rcmd: address size: %d larger than limit %d\n"),
126 hp
->h_length
, sizeof (sin
.sin_addr
));
127 return (MYRCMD_EBAD
);
131 bzero((char *)&newaction
, sizeof (newaction
));
132 newaction
.sa_handler
= SIG_IGN
;
133 newaction
.sa_flags
= SA_ONSTACK
;
134 (void) sigaction(SIGPIPE
, &newaction
, &oldaction
);
137 bzero((char *)&newmask
, sizeof (newmask
));
138 (void) sigaddset(&newmask
, SIGURG
);
139 (void) sigprocmask(SIG_BLOCK
, &newmask
, &oldmask
);
143 * Use 0 as lport means that rresvport() will bind to a port in
144 * the anonymous priviledged port range.
148 s
= rresvport(&lport
);
152 if (errno
== EAGAIN
) {
153 (void) snprintf(myrcmd_stderr
,
154 sizeof (myrcmd_stderr
),
155 gettext("socket: All ports in use\n"));
156 err
= MYRCMD_ENOPORT
;
159 (void) snprintf(myrcmd_stderr
,
160 sizeof (myrcmd_stderr
),
161 gettext("rcmd: socket: %s\n"),
163 err
= MYRCMD_ENOSOCK
;
165 /* restore original SIGPIPE handler */
166 (void) sigaction(SIGPIPE
, &oldaction
,
167 (struct sigaction
*)0);
169 /* restore original signal mask */
170 (void) sigprocmask(SIG_SETMASK
, &oldmask
,
174 /* Can't fail, according to fcntl(2) */
175 (void) fcntl(s
, F_SETOWN
, pid
);
176 sin
.sin_family
= hp
->h_addrtype
;
177 bcopy(hp
->h_addr_list
[0], (caddr_t
)&sin
.sin_addr
, hp
->h_length
);
178 sin
.sin_port
= rport
;
179 if (connect(s
, (struct sockaddr
*)&sin
, sizeof (sin
)) >= 0)
183 if (saverr
== EADDRINUSE
) {
186 if (saverr
== ECONNREFUSED
&& timo
<= 16) {
191 if (hp
->h_addr_list
[1] != NULL
) {
195 gettext("connect to address %s: "),
196 inet_ntoa(sin
.sin_addr
));
200 bcopy(hp
->h_addr_list
[0], (caddr_t
)&sin
.sin_addr
,
202 fprintf(stderr
, gettext("Trying %s...\n"),
203 inet_ntoa(sin
.sin_addr
));
206 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
207 "%s: %s\n", hp
->h_name
, strerror(saverr
));
208 /* restore original SIGPIPE handler */
209 (void) sigaction(SIGPIPE
, &oldaction
,
210 (struct sigaction
*)0);
212 /* restore original signal mask */
213 (void) sigprocmask(SIG_SETMASK
, &oldmask
, (sigset_t
*)0);
214 return (MYRCMD_ENOCONNECT
);
216 if (write(s
, "", 1) < 0) {
218 return (MYRCMD_ENOCONNECT
);
221 loclen
= strlen(locuser
) + 1;
222 remlen
= strlen(remuser
) + 1;
223 cmdlen
= strlen(cmd
) + 1;
225 if (((retval
= write(s
, locuser
, loclen
)) != loclen
) ||
226 ((retval
= write(s
, remuser
, remlen
)) != remlen
) ||
227 ((retval
= write(s
, cmd
, cmdlen
)) != cmdlen
)) {
229 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
230 "write: %s\n", strerror(errno
));
232 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
233 gettext("write unexpectedly truncated\n"));
236 retval
= read(s
, &c
, 1);
240 * Solaris 2.0 bug alert. Sometimes, if the
241 * tapehost is a Solaris 2.0 system, the connection
242 * will be dropped at this point. Let's try again,
243 * three times, before we throw in the towel.
249 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
250 gettext("Protocol error, %s closed connection\n"),
252 } else if (retval
< 0) {
253 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
254 "%s: %s\n", *ahost
, strerror(errno
));
256 (void) snprintf(myrcmd_stderr
, sizeof (myrcmd_stderr
),
257 gettext("Protocol error, %s sent %d bytes\n"),
263 char *cp
= myrcmd_stderr
;
264 char *ecp
= &myrcmd_stderr
[sizeof (myrcmd_stderr
) - 1];
266 while (read(s
, &c
, 1) == 1) {
268 if (c
== '\n' || cp
>= ecp
)
274 /* restore original SIGPIPE handler */
275 (void) sigaction(SIGPIPE
, &oldaction
, (struct sigaction
*)0);
277 /* restore original signal mask */
278 (void) sigprocmask(SIG_SETMASK
, &oldmask
, (sigset_t
*)0);
282 /* restore original SIGPIPE handler */
283 (void) sigaction(SIGPIPE
, &oldaction
, (struct sigaction
*)0);
285 /* restore original signal mask */
286 (void) sigprocmask(SIG_SETMASK
, &oldmask
, (sigset_t
*)0);
287 return (MYRCMD_EBAD
);