1 /* rcmd.c --- execute a command on a remote host from Windows NT
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 Jim Blandy <jimb@cyclic.com> --- August 1995 */
23 #include <sys/socket.h>
28 /* The rest of this file contains the rcmd() code, which is used
29 only by START_SERVER. The idea for a long-term direction is
30 that this code can be made portable (by using SOCK_ERRNO and
31 so on), and then moved to client.c or someplace it can be
32 shared with the VMS port and any other ports which may want it. */
36 resolve_address (const char **ahost, struct sockaddr_in *sai)
39 unsigned long addr = inet_addr (*ahost);
41 if (addr != (unsigned long) -1)
43 sai->sin_family = AF_INET;
44 sai->sin_addr.s_addr = addr;
50 struct hostent *e = gethostbyname (*ahost);
54 assert (e->h_addrtype == AF_INET);
57 sai->sin_family = AF_INET;
58 memcpy (&sai->sin_addr, e->h_addr, sizeof (sai->sin_addr));
63 error (1, 0, "no such host %s", *ahost);
64 /* Shut up gcc -Wall. */
69 bind_and_connect (struct sockaddr_in *server_sai)
72 struct sockaddr_in client_sai;
75 client_sai.sin_family = AF_INET;
76 client_sai.sin_addr.s_addr = htonl (INADDR_ANY);
78 for (client_port = IPPORT_RESERVED - 1;
79 client_port >= IPPORT_RESERVED/2;
83 client_sai.sin_port = htons (client_port);
85 if ((s = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
86 error (1, 0, "cannot create socket: %s",
87 SOCK_STRERROR (SOCK_ERRNO));
89 result = bind (s, (struct sockaddr *) &client_sai,
92 if (result == SOCKET_ERROR)
95 if (errcode == WSAEADDRINUSE)
98 error (1, 0, "cannot bind to socket: %s",
99 SOCK_STRERROR (errcode));
102 result = connect (s, (struct sockaddr *) server_sai,
103 sizeof (*server_sai));
104 errcode = SOCK_ERRNO;
105 if (result == SOCKET_ERROR)
108 if (errcode == WSAEADDRINUSE)
111 error (1, 0, "cannot connect to socket: %s",
112 SOCK_STRERROR (errcode));
118 error (1, 0, "cannot find free port");
119 /* Shut up gcc -Wall. */
124 rcmd_authenticate (int fd, char *locuser, char *remuser, char *command)
126 /* Send them a bunch of information, each terminated by '\0':
127 - secondary stream port number (we don't use this)
128 - username on local machine
129 - username on server machine
131 Now, the Ultrix man page says you transmit the username on the
132 server first, but that doesn't seem to work. Transmitting the
133 client username first does. Go figure. The Linux man pages
134 get it right --- hee hee. */
135 if ((send (fd, "0\0", 2, 0) == SOCKET_ERROR)
136 || (send (fd, locuser, strlen (locuser) + 1, 0) == SOCKET_ERROR)
137 || (send (fd, remuser, strlen (remuser) + 1, 0) == SOCKET_ERROR)
138 || (send (fd, command, strlen (command) + 1, 0) == SOCKET_ERROR))
139 error (1, 0, "cannot send authentication info to rshd: %s",
140 SOCK_STRERROR (SOCK_ERRNO));
142 /* They sniff our butt, and send us a '\0' character if they
146 if (recv (fd, &c, 1, 0) == SOCKET_ERROR)
148 error (1, 0, "cannot receive authentication info from rshd: %s",
149 SOCK_STRERROR (SOCK_ERRNO));
153 /* All the junk with USER, LOGNAME, GetUserName, &c, is so
154 confusing that we better give some clue as to what sort
155 of user name we decided on. */
156 error (0, 0, "cannot log in as local user '%s', remote user '%s'",
158 error (1, 0, "Permission denied by rshd");
166 rcmd (const char **ahost,
167 unsigned short inport,
173 struct sockaddr_in sai;
178 if (resolve_address (ahost, &sai) < 0)
179 error (1, 0, "internal error: resolve_address < 0");
181 sai.sin_port = htons (inport);
183 if ((s = bind_and_connect (&sai)) == INVALID_SOCKET)
184 error (1, 0, "internal error: bind_and_connect < 0");
186 if (rcmd_authenticate (s, locuser, remuser, cmd) < 0)
187 error (1, 0, "internal error: rcmd_authenticate < 0");