* [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).