9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] win32 listen1 + Named pipes + rshd
@ 2003-07-11  9:23 steve.simon
  0 siblings, 0 replies; only message in thread
From: steve.simon @ 2003-07-11  9:23 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 559 bytes --]

Hi,

I wrote a listen1.c and a toy rxd.c as native windows apps.

The code seems OK to me but others my cringe at my
implementation, I have no need nor wish to properly
learn the win32 api - your mileage may vary.

I use it to run crosscompilers and u9fs on a WinNT
system.

I planed to add build p9any authentication into the rxd,
though the plan9 cpu protocol fits my needs better,
propogation of signals and remote execution in the same
directory. If I can work out how to get Win32 to do TLS
I might have a go at that too somtime.

-Steve

[-- Attachment #2: listen1.c --]
[-- Type: text/plain, Size: 8917 bytes --]

/* listen1.c - network listener */

#include <winsock2.h>
#include <process.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>

#define MAX_MSG		8200		/* buffer size */

typedef struct {
	int skt;
	HANDLE rd;
	HANDLE wr;
	HANDLE event;
} session;

char *argv0;
char *Program;
int Debug = 0;

int main(int argc, char *argv[]);
unsigned long parseip(char *to, char *from);
char *ipaddr(unsigned long ip);
void work(void *p);
HANDLE child(HANDLE std_in, HANDLE std_out);
unsigned int __stdcall thr_read(void *vp);
unsigned int __stdcall thr_write(void *vp);
int errmsg(char *s, ...);

int
main(int argc, char *argv[])
{
	char *p, *q, to[4];
	char buf[2048];
	int on, n, port, fd, nfd;
	struct servent *serv;
	struct sockaddr_in addr, peer;
	struct hostent *hp;
	WSADATA wsadata;

	argv0 = argv[0];

	if (WSAStartup(MAKEWORD(1, 1), &wsadata) != 0){
		errmsg("WSAStartup failed\n");
		return(0);
	}

	if (strcmp(argv[1], "-d") == 0){
		Debug = 1;
		argc--;
		argv++;
	}

	if (argc < 3){
		fprintf(stderr, "usage: %s [-v] tcp!ipaddr!port prog.exe\n", argv0);
		goto sysfatal;
	}

	Program = argv[2];

	strcpy(buf, argv[1]);
	p = strchr(buf, '!');
	if(p == 0){
		fprintf(stderr, "bad address syntax\n");
		goto sysfatal;
	}
	q = strchr(p+1, '!');
	if(q == 0){
		fprintf(stderr, "bad address syntax\n");
		goto sysfatal;
	}
	*p++ = 0;
	*q++ = 0;

	if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1){
		errmsg("socket failed");
		goto sysfatal;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;

	if ((serv = getservbyname(q, buf)) != NULL)
		addr.sin_port = serv->s_port;
	else
	if (strcmp(buf, "tcp") == 0 && (port = atoi(q)) != 0)
		addr.sin_port = htons(port);
	else {
		errmsg("bad port", argv[1]);
		goto sysfatal;
	}

	if (strcmp(p, "*") == 0)
		addr.sin_addr.s_addr = INADDR_ANY;
	else
		addr.sin_addr.s_addr = htonl(parseip(to, p));

	if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1){
		errmsg("bind failed");
		goto sysfatal;
	}

	if (listen(fd, SOMAXCONN) == -1){
		errmsg("listen failed");
		goto sysfatal;
	}

	while (1){
		n = sizeof(peer);
		if ((nfd = accept(fd, (struct sockaddr *)&peer, &n)) == -1){
			errmsg("accept failed");
			goto sysfatal;
		}

		if ((hp = gethostbyaddr((char *)&peer.sin_addr, n, peer.sin_family)) != NULL)
			SetEnvironmentVariable("REMOTEHOST", hp->h_name);
		else
			SetEnvironmentVariable("REMOTEHOST", ipaddr(ntohl(peer.sin_addr.s_addr)));
		on = 1;
		if (setsockopt(nfd, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)) != 0)
			errmsg("setsockopt keepalive failed");

		on = 1;
		if (setsockopt(nfd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)) != 0)
			errmsg("setsockopt nodelay failed");

		on = MAX_MSG;
		if (setsockopt(nfd, SOL_SOCKET, SO_SNDBUF, (char*)&on, sizeof(on)) != 0)
			errmsg("setsockopt sndbuf failed");

		on = MAX_MSG;
		if (setsockopt(nfd, SOL_SOCKET, SO_RCVBUF, (char*)&on, sizeof(on)) != 0)
			errmsg("setsockopt rcvbuf failed");

		if(setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) != 0)
			errmsg("setsockopt reuseaddr failed");

		_beginthread(work, 0, (void *)nfd);
	}

sysfatal:
	if (fd){
		shutdown(fd, SD_BOTH);
		closesocket(fd);
	}
	WSACleanup();
	return(0);
}


void
work(void *p)
{
	session ss;
	unsigned tid;
	SOCKET skt = (SOCKET)p;
	SECURITY_ATTRIBUTES sa;
	HANDLE proc = 0, rd = 0, wr = 0, rt = 0, wt = 0, ha[2] = {0,0};

	memset(&ss, 0, sizeof(ss));
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	if (CreatePipe(&ss.rd, &wr, &sa, MAX_MSG) == FALSE)
		goto cleanup;

	if (CreatePipe(&rd, &ss.wr, &sa, MAX_MSG) == FALSE)
		goto cleanup;

	if ((proc = child(rd, wr)) == 0)
		goto cleanup;

	CloseHandle(rd);
	rd = 0;

	CloseHandle(wr);
	wr = 0;

	if ((ss.event = CreateEvent(NULL, TRUE, FALSE, NULL)) == 0)
		return;

	ss.skt = skt;

	if ((rt = (HANDLE)_beginthreadex(NULL, 0, thr_read, (void *)&ss, 0, &tid)) == 0)
		return;

	if ((wt = (HANDLE) _beginthreadex(NULL, 0, thr_write, (void *)&ss, 0, &tid)) == 0){
		SetEvent(ss.event);
		WaitForSingleObject(rt, INFINITE);
		ResetEvent(ss.event);
		goto cleanup;
	}

	WaitForSingleObject(proc, INFINITE);
	ha[0] = rt;
	ha[1] = wt;
	SetEvent(ss.event);
	WaitForMultipleObjects(2, ha, TRUE, INFINITE);
	ResetEvent(ss.event);

cleanup:
	if (rd)
		CloseHandle(rd);
	if (wr)
		CloseHandle(wr);
	if (ss.rd)
		CloseHandle(ss.rd);
	if (ss.wr)
		CloseHandle(ss.wr);
	if (ss.event)
		CloseHandle(ss.event);
	if (rt)
		CloseHandle(rt);
	if (wt)
		CloseHandle(wt);
	if (proc)
		CloseHandle(proc);
	shutdown(skt, SD_BOTH);
	closesocket(skt);
}


HANDLE
child(HANDLE std_in, HANDLE std_out)
{
	STARTUPINFO si;
	PROCESS_INFORMATION pi;

	memset(&si, 0, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
	si.hStdInput = std_in;
	si.hStdOutput = std_out;

	DuplicateHandle(GetCurrentProcess(), std_out, GetCurrentProcess(),
		&si.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS);

	if (CreateProcess(NULL, Program, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi) == 0){
		errmsg("cannot start %s", Program);
		return(0);
	}
	CloseHandle(pi.hThread);

	return pi.hProcess;
}

unsigned int __stdcall
thr_read(void *vp)
{
	unsigned long len, xfer;
	char *p, buf[MAX_MSG], *pos;
	session *ss = (session *)vp;

	while (1) {
		if (WaitForSingleObject(ss->event, 0) == WAIT_OBJECT_0)
			break;
		if (PeekNamedPipe(ss->rd, buf, sizeof(buf), &len, NULL, NULL) == NULL)
			break;
		if (len == 0){
			Sleep(10);
			continue;
		}

		if (!ReadFile(ss->rd, buf, sizeof(buf), &len, 0))
			break;
		pos = buf;

		if (Debug){
			fprintf(stderr, "-> ");
			for (p = pos; p < pos + len; p++)
				if ((*p < ' ' || *p > '~') && *p != '\n')
					fprintf(stderr, "\\x%02x", *p);
				else
					fprintf(stderr, "%c", *p);
			fprintf(stderr, "\n");
		}

again:
		if ((xfer = send(ss->skt, pos, len, 0)) <= 0)
			break;
		if (xfer < len){		/* paranoia */
			len -= xfer;
			pos += xfer;
			goto again;
		}
	}
	return(0);
}

unsigned int __stdcall
thr_write(void *vp)
{
	int err;
	fd_set rd;
	struct timeval tout;
	unsigned long len, xfer;
	char *p, buf[MAX_MSG], *pos;
	session *ss = (session *)vp;

	tout.tv_sec = 0;
	tout.tv_usec = 100000;

	while (1) {
		if (WaitForSingleObject(ss->event, 0) == WAIT_OBJECT_0)
			break;
		FD_ZERO(&rd);
		FD_SET((unsigned int)ss->skt, &rd);
		if ((err = select(ss->skt + 1, &rd, NULL, NULL, &tout)) < 0)
			break;
		if (err == 0)
			continue;

		if ((len = recv(ss->skt, buf, sizeof(buf), 0)) <= 0)
			break;

		pos = buf;

		if (Debug){
			fprintf(stderr, "<- ");
			for (p = pos; p < pos + len; p++)
				if ((*p < ' ' || *p > '~') && *p != '\n')
					fprintf(stderr, "\\x%02x", *p);
				else
					fprintf(stderr, "%c", *p);
			fprintf(stderr, "\n");
		}

again:
		if (!WriteFile(ss->wr, pos, len, &xfer, 0)){
			if (Debug)
				fprintf(stderr, "WriteFile failed\n");
			break;
		}

		if (xfer < len){		/* paranoia */
			len -= xfer;
			pos += xfer;
			goto again;
		}
	}
	return(0);
}

int
errmsg(char *s, ...)	/* NB: this is not sysfatal() - its not fatal. */
{
	char msg[128];
	va_list args;

	fprintf(stderr, "%s: ", argv0);

	va_start(args, s);
	vfprintf(stderr, s, args);
	va_end(args);

	if (GetLastError()){
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
			GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			msg, sizeof(msg), 0);
		fprintf(stderr, " %lu/%s", (unsigned long)GetLastError(), msg);
	}
	if (WSAGetLastError()){
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
			WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			msg, sizeof(msg), 0);
		fprintf(stderr, " %lu/%s", (unsigned long)WSAGetLastError(), msg);
	}

	fputc('\n', stderr);

	return(1);
}

char *
ipaddr(unsigned long ip)
{
	static char buf[20];

	snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
		(ip >> 24) & 0xff,
		(ip >> 16) & 0xff,
		(ip >> 8) & 0xff,
		(ip >> 0) & 0xff);
	return(buf);
}


#define CLASS(p) ((*(unsigned char*)(p))>>6)

unsigned long
parseip(char *to, char *from)
{
	int i;
	char *p;

	p = from;
	memset(to, 0, 4);
	for(i = 0; i < 4 && *p; i++){
		to[i] = strtoul(p, &p, 0);
		if(*p == '.')
			p++;
	}
	switch(CLASS(to)){
	case 0:	/* class A - 1 byte net */
	case 1:
		if(i == 3){
			to[3] = to[2];
			to[2] = to[1];
			to[1] = 0;
		} else if (i == 2){
			to[3] = to[1];
			to[1] = 0;
		}
		break;
	case 2:	/* class B - 2 byte net */
		if(i == 3){
			to[3] = to[2];
			to[2] = 0;
		}
		break;
	}
	return ntohl(*(unsigned long *)to);
}

[-- Attachment #3: rxd.c --]
[-- Type: text/plain, Size: 1649 bytes --]

#include <windows.h>
#include <stdio.h>
#include <ctype.h>

static void
getstr(HANDLE h, char *s, int n)
{
	char c;
	unsigned long got;

	while (n--){
		if (ReadFile(h, &c, 1, &got, NULL) == 0)
			break;
		if (got != 1)
			break;
		*s++ = c;
		if (c == 0)
			break;
	}
}

static void
putstr(HANDLE h, char *s)
{
	unsigned long got;
	WriteFile(h, s, strlen(s) +1, &got, NULL);
}

void
main()
{
	int cmdlen;
	HANDLE inp, out;
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	unsigned long len;
	char errport[24], remuser[24], locuser[24],
		cmd[4096], iam[1024];

	if (!GetEnvironmentVariable("COMSPEC", cmd, sizeof(cmd)))
		strcpy(cmd, "cmd.exe");
	strcat(cmd, " /c ");
	cmdlen = strlen(cmd);

        inp = GetStdHandle(STD_INPUT_HANDLE);
        out = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleMode(inp, ENABLE_PROCESSED_INPUT);
        SetConsoleMode(out, 0);

	getstr(inp, errport, sizeof(errport));
	getstr(inp, remuser, sizeof(remuser));
	getstr(inp, locuser, sizeof(locuser));
	getstr(inp, cmd + cmdlen, sizeof(cmd) - cmdlen);

	len = sizeof(iam);
	GetUserName(iam, &len);
	if (strcmp(iam, locuser) != 0){
		putstr(out, "xAuthentication failed\n");
		Sleep(100);
		exit(1);
	}

	putstr(out, "");
	Sleep(10);

	memset(&pi, 0, sizeof(pi));
	memset(&si, 0, sizeof(si));
	si.cb = sizeof(si);

	if( !CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)){
		fprintf(stderr, "'%s' exec failed\n", cmd);
		Sleep(100);
		exit(1);
	}
	Sleep(100);
	WaitForSingleObject(pi.hProcess, INFINITE);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	exit(0);
}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-07-11  9:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-11  9:23 [9fans] win32 listen1 + Named pipes + rshd steve.simon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).