home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
cvs-1.8.7-src.tgz
/
tar.out
/
fsf
/
cvs
/
windows-NT
/
rcmd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
5KB
|
220 lines
/* rcmd.c --- execute a command on a remote host from Windows NT
Jim Blandy <jimb@cyclic.com> --- August 1995 */
#include <io.h>
#include <fcntl.h>
#include <malloc.h>
#include <errno.h>
#include <winsock.h>
#include <stdio.h>
#include <assert.h>
#include "rcmd.h"
void
init_winsock ()
{
WSADATA data;
int optionValue = SO_SYNCHRONOUS_NONALERT;
if (WSAStartup (MAKEWORD (1, 1), &data))
{
fprintf (stderr, "cvs: unable to initialize winsock\n");
exit (1);
}
if (setsockopt(INVALID_SOCKET, SOL_SOCKET,
SO_OPENTYPE, (char *)&optionValue, sizeof(optionValue))
== SOCKET_ERROR)
{
fprintf (stderr, "cvs: unable to setup winsock\n");
exit (1);
}
}
static int
resolve_address (const char **ahost, struct sockaddr_in *sai)
{
{
unsigned long addr = inet_addr (*ahost);
if (addr != (unsigned long) -1)
{
sai->sin_family = AF_INET;
sai->sin_addr.s_addr = addr;
return 0;
}
}
{
struct hostent *e = gethostbyname (*ahost);
if (e)
{
assert (e->h_addrtype == AF_INET);
assert (e->h_addr);
*ahost = e->h_name;
sai->sin_family = AF_INET;
memcpy (&sai->sin_addr, e->h_addr, sizeof (sai->sin_addr));
return 0;
}
}
return -1;
}
#if 0
static int
bind_local_end (SOCKET s)
{
struct sockaddr_in sai;
int result;
u_short port;
sai.sin_family = AF_INET;
sai.sin_addr.s_addr = htonl (INADDR_ANY);
for (port = IPPORT_RESERVED - 2; port >= IPPORT_RESERVED/2; port--)
{
int error;
sai.sin_port = htons (port);
result = bind (s, (struct sockaddr *) &sai, sizeof (sai));
error = GetLastError ();
if (result != SOCKET_ERROR || error != WSAEADDRINUSE)
break;
}
return result;
}
#endif
static SOCKET
bind_and_connect (struct sockaddr_in *server_sai)
{
SOCKET s;
struct sockaddr_in client_sai;
u_short client_port;
client_sai.sin_family = AF_INET;
client_sai.sin_addr.s_addr = htonl (INADDR_ANY);
for (client_port = IPPORT_RESERVED - 1;
client_port >= IPPORT_RESERVED/2;
client_port--)
{
int result, error;
client_sai.sin_port = htons (client_port);
if ((s = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return INVALID_SOCKET;
result = bind (s, (struct sockaddr *) &client_sai,
sizeof (client_sai));
error = GetLastError ();
if (result == SOCKET_ERROR)
{
closesocket (s);
if (error == WSAEADDRINUSE)
continue;
else
return INVALID_SOCKET;
}
result = connect (s, (struct sockaddr *) server_sai,
sizeof (*server_sai));
error = GetLastError ();
if (result == SOCKET_ERROR)
{
closesocket (s);
if (error == WSAEADDRINUSE)
continue;
else
return INVALID_SOCKET;
}
return s;
}
/* We couldn't find a free port. */
return INVALID_SOCKET;
}
static int
rcmd_authenticate (int fd, char *locuser, char *remuser, char *command)
{
/* Send them a bunch of information, each terminated by '\0':
- secondary stream port number (we don't use this)
- username on local machine
- username on server machine
- command
Now, the Ultrix man page says you transmit the username on the
server first, but that doesn't seem to work. Transmitting the
client username first does. Go figure. The Linux man pages
get it right --- hee hee. */
if (write (fd, "0\0", 2) < 0
|| write (fd, locuser, strlen (locuser) + 1) < 0
|| write (fd, remuser, strlen (remuser) + 1) < 0
|| write (fd, command, strlen (command) + 1) < 0)
return -1;
/* They sniff our butt, and send us a '\0' character if they
like us. */
{
char c;
if (read (fd, &c, 1) <= 0
|| c != '\0')
{
errno = EPERM;
return -1;
}
}
return 0;
}
int
rcmd (const char **ahost,
unsigned short inport,
char *locuser,
char *remuser,
char *cmd,
int *fd2p)
{
struct sockaddr_in sai;
SOCKET s;
int fd;
assert (fd2p == 0);
if (resolve_address (ahost, &sai) < 0)
return -1;
sai.sin_port = htons (inport);
#if 0
if ((s = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return -1;
if (bind_local_end (s) < 0)
return -1;
if (connect (s, (struct sockaddr *) &sai, sizeof (sai))
== SOCKET_ERROR)
return -1;
#else
if ((s = bind_and_connect (&sai)) == INVALID_SOCKET)
return -1;
#endif
/* When using WinSock under Windows NT, sockets are low-level Windows
NT handles. Turn the socket we've made into a Unix-like file
descriptor. */
if ((fd = _open_osfhandle (s, _O_BINARY)) < 0)
return -1;
if (rcmd_authenticate (fd, locuser, remuser, cmd) < 0)
return -1;
return fd;
}