xref: /plan9/sys/src/cmd/unix/winplumb.c (revision a6a9e07217f318acf170f99684a55fba5200524f)
1*a6a9e072SDavid du Colombier #include <windows.h>
2*a6a9e072SDavid du Colombier #include <stdio.h>
3*a6a9e072SDavid du Colombier 
4*a6a9e072SDavid du Colombier #pragma comment(lib, "wsock32.lib")
5*a6a9e072SDavid du Colombier #pragma comment(lib, "shell32.lib")
6*a6a9e072SDavid du Colombier 
7*a6a9e072SDavid du Colombier char	*argv0 = "winplumb";
8*a6a9e072SDavid du Colombier char errbuf[256];
9*a6a9e072SDavid du Colombier unsigned long parseip(char*, char*);
10*a6a9e072SDavid du Colombier typedef unsigned long ulong;
11*a6a9e072SDavid du Colombier void oserror(void);
12*a6a9e072SDavid du Colombier 
13*a6a9e072SDavid du Colombier void
hnputl(void * p,unsigned long v)14*a6a9e072SDavid du Colombier hnputl(void *p, unsigned long v)
15*a6a9e072SDavid du Colombier {
16*a6a9e072SDavid du Colombier 	unsigned char *a;
17*a6a9e072SDavid du Colombier 
18*a6a9e072SDavid du Colombier 	a = p;
19*a6a9e072SDavid du Colombier 	a[0] = v>>24;
20*a6a9e072SDavid du Colombier 	a[1] = v>>16;
21*a6a9e072SDavid du Colombier 	a[2] = v>>8;
22*a6a9e072SDavid du Colombier 	a[3] = v;
23*a6a9e072SDavid du Colombier }
24*a6a9e072SDavid du Colombier 
25*a6a9e072SDavid du Colombier void
hnputs(void * p,unsigned short v)26*a6a9e072SDavid du Colombier hnputs(void *p, unsigned short v)
27*a6a9e072SDavid du Colombier {
28*a6a9e072SDavid du Colombier 	unsigned char *a;
29*a6a9e072SDavid du Colombier 
30*a6a9e072SDavid du Colombier 	a = p;
31*a6a9e072SDavid du Colombier 	a[0] = v>>8;
32*a6a9e072SDavid du Colombier 	a[1] = v;
33*a6a9e072SDavid du Colombier }
34*a6a9e072SDavid du Colombier 
35*a6a9e072SDavid du Colombier unsigned long
nhgetl(void * p)36*a6a9e072SDavid du Colombier nhgetl(void *p)
37*a6a9e072SDavid du Colombier {
38*a6a9e072SDavid du Colombier 	unsigned char *a;
39*a6a9e072SDavid du Colombier 	a = p;
40*a6a9e072SDavid du Colombier 	return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
41*a6a9e072SDavid du Colombier }
42*a6a9e072SDavid du Colombier 
43*a6a9e072SDavid du Colombier unsigned short
nhgets(void * p)44*a6a9e072SDavid du Colombier nhgets(void *p)
45*a6a9e072SDavid du Colombier {
46*a6a9e072SDavid du Colombier 	unsigned char *a;
47*a6a9e072SDavid du Colombier 	a = p;
48*a6a9e072SDavid du Colombier 	return (a[0]<<8)|(a[1]<<0);
49*a6a9e072SDavid du Colombier }
50*a6a9e072SDavid du Colombier 
51*a6a9e072SDavid du Colombier 
52*a6a9e072SDavid du Colombier int
main(int argc,char ** argv)53*a6a9e072SDavid du Colombier main(int argc, char **argv)
54*a6a9e072SDavid du Colombier {
55*a6a9e072SDavid du Colombier 	char *addr, *p, *q, to[4];
56*a6a9e072SDavid du Colombier 	char buf[2048];
57*a6a9e072SDavid du Colombier 	int port, fd, nfd, one, len, n, tot;
58*a6a9e072SDavid du Colombier 	ulong ip;
59*a6a9e072SDavid du Colombier 	struct sockaddr_in sin;
60*a6a9e072SDavid du Colombier 	WSADATA wasdat;
61*a6a9e072SDavid du Colombier 
62*a6a9e072SDavid du Colombier 	if(argc != 1 && argc != 2){
63*a6a9e072SDavid du Colombier 	usage:
64*a6a9e072SDavid du Colombier 		fprintf(stderr, "usage: winplumb [tcp!ipaddr!port]\n");
65*a6a9e072SDavid du Colombier 		ExitThread(1);
66*a6a9e072SDavid du Colombier 	}
67*a6a9e072SDavid du Colombier 
68*a6a9e072SDavid du Colombier 	if(argc == 1)
69*a6a9e072SDavid du Colombier 		addr = "tcp!*!17890";
70*a6a9e072SDavid du Colombier 	else
71*a6a9e072SDavid du Colombier 		addr = argv[1];
72*a6a9e072SDavid du Colombier 
73*a6a9e072SDavid du Colombier 	strcpy(buf, addr);
74*a6a9e072SDavid du Colombier 	p = strchr(buf, '!');
75*a6a9e072SDavid du Colombier 	if(p == 0)
76*a6a9e072SDavid du Colombier 		goto usage;
77*a6a9e072SDavid du Colombier 	q = strchr(p+1, '!');
78*a6a9e072SDavid du Colombier 	if(q == 0)
79*a6a9e072SDavid du Colombier 		goto usage;
80*a6a9e072SDavid du Colombier 	*p++ = 0;
81*a6a9e072SDavid du Colombier 	*q++ = 0;
82*a6a9e072SDavid du Colombier 
83*a6a9e072SDavid du Colombier 	if(strcmp(buf, "tcp") != 0)
84*a6a9e072SDavid du Colombier 		goto usage;
85*a6a9e072SDavid du Colombier 
86*a6a9e072SDavid du Colombier 	port = atoi(q);
87*a6a9e072SDavid du Colombier 	if(strcmp(p, "*") == 0)
88*a6a9e072SDavid du Colombier 		ip = 0;
89*a6a9e072SDavid du Colombier 	else
90*a6a9e072SDavid du Colombier 		ip = parseip(to, p);
91*a6a9e072SDavid du Colombier 
92*a6a9e072SDavid du Colombier 	WSAStartup(MAKEWORD(1, 1), &wasdat);
93*a6a9e072SDavid du Colombier 
94*a6a9e072SDavid du Colombier 
95*a6a9e072SDavid du Colombier 	fd = socket(AF_INET, SOCK_STREAM, 0);
96*a6a9e072SDavid du Colombier 	if(fd < 0){
97*a6a9e072SDavid du Colombier 		oserror();
98*a6a9e072SDavid du Colombier 		fprintf(stderr, "socket: %s\n", errbuf);
99*a6a9e072SDavid du Colombier 		ExitThread(1);
100*a6a9e072SDavid du Colombier 	}
101*a6a9e072SDavid du Colombier 
102*a6a9e072SDavid du Colombier 	one = 1;
103*a6a9e072SDavid du Colombier 	if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one) != 0){
104*a6a9e072SDavid du Colombier 		oserror();
105*a6a9e072SDavid du Colombier 		fprintf(stderr, "setsockopt nodelay: %s\n", errbuf);
106*a6a9e072SDavid du Colombier 	}
107*a6a9e072SDavid du Colombier 
108*a6a9e072SDavid du Colombier 	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof one) != 0){
109*a6a9e072SDavid du Colombier 		oserror();
110*a6a9e072SDavid du Colombier 		fprintf(stderr, "setsockopt reuse: %s\n", errbuf);
111*a6a9e072SDavid du Colombier 	}
112*a6a9e072SDavid du Colombier 	memset(&sin, 0, sizeof sin);
113*a6a9e072SDavid du Colombier 	sin.sin_family = AF_INET;
114*a6a9e072SDavid du Colombier 	hnputs(&sin.sin_port, port);
115*a6a9e072SDavid du Colombier 	hnputl(&sin.sin_addr, ip);
116*a6a9e072SDavid du Colombier 	if(bind(fd, (struct sockaddr*)&sin, sizeof sin) < 0){
117*a6a9e072SDavid du Colombier 		oserror();
118*a6a9e072SDavid du Colombier 		fprintf(stderr, "bind: %s\n", errbuf);
119*a6a9e072SDavid du Colombier 		ExitThread(1);
120*a6a9e072SDavid du Colombier 	}
121*a6a9e072SDavid du Colombier 
122*a6a9e072SDavid du Colombier 	if(listen(fd, 5) < 0){
123*a6a9e072SDavid du Colombier 		oserror();
124*a6a9e072SDavid du Colombier 		fprintf(stderr, "listen: %s\n", errbuf);
125*a6a9e072SDavid du Colombier 		ExitThread(1);
126*a6a9e072SDavid du Colombier 	}
127*a6a9e072SDavid du Colombier 
128*a6a9e072SDavid du Colombier 	for(;;){
129*a6a9e072SDavid du Colombier 		len = sizeof sin;
130*a6a9e072SDavid du Colombier 		nfd = accept(fd, (struct sockaddr*)&sin, &len);
131*a6a9e072SDavid du Colombier 		if(nfd < 0){
132*a6a9e072SDavid du Colombier 			oserror();
133*a6a9e072SDavid du Colombier 			fprintf(stderr, "accept: %s\n", errbuf);
134*a6a9e072SDavid du Colombier 			continue;
135*a6a9e072SDavid du Colombier 		}
136*a6a9e072SDavid du Colombier 		tot = 0;
137*a6a9e072SDavid du Colombier 		while(tot == 0 || buf[tot-1] != '\n'){
138*a6a9e072SDavid du Colombier 			n = recv(nfd, buf+tot, sizeof buf-tot, 0);
139*a6a9e072SDavid du Colombier 			if(n < 0)
140*a6a9e072SDavid du Colombier 				break;
141*a6a9e072SDavid du Colombier 			tot += n;
142*a6a9e072SDavid du Colombier 		}
143*a6a9e072SDavid du Colombier 		if(buf[tot-1] == '\n'){
144*a6a9e072SDavid du Colombier 			buf[tot-1] = 0;
145*a6a9e072SDavid du Colombier 			p = strchr(buf, ' ');
146*a6a9e072SDavid du Colombier 			if(p)
147*a6a9e072SDavid du Colombier 				*p++ = 0;
148*a6a9e072SDavid du Colombier 			ShellExecute(0, 0, buf, p, 0, SW_SHOWNORMAL);
149*a6a9e072SDavid du Colombier 		}
150*a6a9e072SDavid du Colombier 		closesocket(nfd);
151*a6a9e072SDavid du Colombier 	}
152*a6a9e072SDavid du Colombier }
153*a6a9e072SDavid du Colombier 
154*a6a9e072SDavid du Colombier 
155*a6a9e072SDavid du Colombier #define CLASS(p) ((*(unsigned char*)(p))>>6)
156*a6a9e072SDavid du Colombier 
157*a6a9e072SDavid du Colombier 
158*a6a9e072SDavid du Colombier unsigned long
parseip(char * to,char * from)159*a6a9e072SDavid du Colombier parseip(char *to, char *from)
160*a6a9e072SDavid du Colombier {
161*a6a9e072SDavid du Colombier 	int i;
162*a6a9e072SDavid du Colombier 	char *p;
163*a6a9e072SDavid du Colombier 
164*a6a9e072SDavid du Colombier 	p = from;
165*a6a9e072SDavid du Colombier 	memset(to, 0, 4);
166*a6a9e072SDavid du Colombier 	for(i = 0; i < 4 && *p; i++){
167*a6a9e072SDavid du Colombier 		to[i] = strtoul(p, &p, 0);
168*a6a9e072SDavid du Colombier 		if(*p == '.')
169*a6a9e072SDavid du Colombier 			p++;
170*a6a9e072SDavid du Colombier 	}
171*a6a9e072SDavid du Colombier 	switch(CLASS(to)){
172*a6a9e072SDavid du Colombier 	case 0:	/* class A - 1 byte net */
173*a6a9e072SDavid du Colombier 	case 1:
174*a6a9e072SDavid du Colombier 		if(i == 3){
175*a6a9e072SDavid du Colombier 			to[3] = to[2];
176*a6a9e072SDavid du Colombier 			to[2] = to[1];
177*a6a9e072SDavid du Colombier 			to[1] = 0;
178*a6a9e072SDavid du Colombier 		} else if (i == 2){
179*a6a9e072SDavid du Colombier 			to[3] = to[1];
180*a6a9e072SDavid du Colombier 			to[1] = 0;
181*a6a9e072SDavid du Colombier 		}
182*a6a9e072SDavid du Colombier 		break;
183*a6a9e072SDavid du Colombier 	case 2:	/* class B - 2 byte net */
184*a6a9e072SDavid du Colombier 		if(i == 3){
185*a6a9e072SDavid du Colombier 			to[3] = to[2];
186*a6a9e072SDavid du Colombier 			to[2] = 0;
187*a6a9e072SDavid du Colombier 		}
188*a6a9e072SDavid du Colombier 		break;
189*a6a9e072SDavid du Colombier 	}
190*a6a9e072SDavid du Colombier 	return nhgetl(to);
191*a6a9e072SDavid du Colombier }
192*a6a9e072SDavid du Colombier 
193*a6a9e072SDavid du Colombier void
oserror(void)194*a6a9e072SDavid du Colombier oserror(void)
195*a6a9e072SDavid du Colombier {
196*a6a9e072SDavid du Colombier 	int e, r, i;
197*a6a9e072SDavid du Colombier 	char buf[200];
198*a6a9e072SDavid du Colombier 
199*a6a9e072SDavid du Colombier 	e = GetLastError();
200*a6a9e072SDavid du Colombier 
201*a6a9e072SDavid du Colombier 	r = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
202*a6a9e072SDavid du Colombier 		0, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
203*a6a9e072SDavid du Colombier 		buf, sizeof(buf), 0);
204*a6a9e072SDavid du Colombier 
205*a6a9e072SDavid du Colombier 	if(r == 0)
206*a6a9e072SDavid du Colombier 		sprintf(buf, "windows error %d", e);
207*a6a9e072SDavid du Colombier 
208*a6a9e072SDavid du Colombier 
209*a6a9e072SDavid du Colombier 	for(i = strlen(buf)-1; i>=0 && buf[i] == '\n' || buf[i] == '\r'; i--)
210*a6a9e072SDavid du Colombier 		buf[i] = 0;
211*a6a9e072SDavid du Colombier 
212*a6a9e072SDavid du Colombier 	strcpy(errbuf, buf);
213*a6a9e072SDavid du Colombier }
214*a6a9e072SDavid du Colombier 
215*a6a9e072SDavid du Colombier extern int	main(int, char*[]);
216*a6a9e072SDavid du Colombier static int	args(char *argv[], int n, char *p);
217*a6a9e072SDavid du Colombier 
218*a6a9e072SDavid du Colombier int PASCAL
WinMain(HANDLE hInst,HANDLE hPrev,LPSTR arg,int nshow)219*a6a9e072SDavid du Colombier WinMain(HANDLE hInst, HANDLE hPrev, LPSTR arg, int nshow)
220*a6a9e072SDavid du Colombier {
221*a6a9e072SDavid du Colombier 	int argc, n;
222*a6a9e072SDavid du Colombier 	char *p, **argv;
223*a6a9e072SDavid du Colombier 
224*a6a9e072SDavid du Colombier 	/* conservative guess at the number of args */
225*a6a9e072SDavid du Colombier 	for(argc=5,p=arg; *p; p++)
226*a6a9e072SDavid du Colombier 		if(*p == ' ' || *p == '\t')
227*a6a9e072SDavid du Colombier 			argc++;
228*a6a9e072SDavid du Colombier 
229*a6a9e072SDavid du Colombier 	argv = malloc(argc*sizeof(char*));
230*a6a9e072SDavid du Colombier 	argc = args(argv+1, argc, arg);
231*a6a9e072SDavid du Colombier 	argc++;
232*a6a9e072SDavid du Colombier 	argv[0] = argv0;
233*a6a9e072SDavid du Colombier 	main(argc, argv);
234*a6a9e072SDavid du Colombier 	ExitThread(0);
235*a6a9e072SDavid du Colombier 	return 0;
236*a6a9e072SDavid du Colombier }
237*a6a9e072SDavid du Colombier 
238*a6a9e072SDavid du Colombier /*
239*a6a9e072SDavid du Colombier  * Break the command line into arguments
240*a6a9e072SDavid du Colombier  * The rules for this are not documented but appear to be the following
241*a6a9e072SDavid du Colombier  * according to the source for the microsoft C library.
242*a6a9e072SDavid du Colombier  * Words are seperated by space or tab
243*a6a9e072SDavid du Colombier  * Words containing a space or tab can be quoted using "
244*a6a9e072SDavid du Colombier  * 2N backslashes + " ==> N backslashes and end quote
245*a6a9e072SDavid du Colombier  * 2N+1 backslashes + " ==> N backslashes + literal "
246*a6a9e072SDavid du Colombier  * N backslashes not followed by " ==> N backslashes
247*a6a9e072SDavid du Colombier  */
248*a6a9e072SDavid du Colombier static int
args(char * argv[],int n,char * p)249*a6a9e072SDavid du Colombier args(char *argv[], int n, char *p)
250*a6a9e072SDavid du Colombier {
251*a6a9e072SDavid du Colombier 	char *p2;
252*a6a9e072SDavid du Colombier 	int i, j, quote, nbs;
253*a6a9e072SDavid du Colombier 
254*a6a9e072SDavid du Colombier 	for(i=0; *p && i<n-1; i++) {
255*a6a9e072SDavid du Colombier 		while(*p == ' ' || *p == '\t')
256*a6a9e072SDavid du Colombier 			p++;
257*a6a9e072SDavid du Colombier 		quote = 0;
258*a6a9e072SDavid du Colombier 		argv[i] = p2 = p;
259*a6a9e072SDavid du Colombier 		for(;*p; p++) {
260*a6a9e072SDavid du Colombier 			if(!quote && (*p == ' ' || *p == '\t'))
261*a6a9e072SDavid du Colombier 				break;
262*a6a9e072SDavid du Colombier 			for(nbs=0; *p == '\\'; p++,nbs++)
263*a6a9e072SDavid du Colombier 				;
264*a6a9e072SDavid du Colombier 			if(*p == '"') {
265*a6a9e072SDavid du Colombier 				for(j=0; j<(nbs>>1); j++)
266*a6a9e072SDavid du Colombier 					*p2++ = '\\';
267*a6a9e072SDavid du Colombier 				if(nbs&1)
268*a6a9e072SDavid du Colombier 					*p2++ = *p;
269*a6a9e072SDavid du Colombier 				else
270*a6a9e072SDavid du Colombier 					quote = !quote;
271*a6a9e072SDavid du Colombier 			} else {
272*a6a9e072SDavid du Colombier 				for(j=0; j<nbs; j++)
273*a6a9e072SDavid du Colombier 					*p2++ = '\\';
274*a6a9e072SDavid du Colombier 				*p2++ = *p;
275*a6a9e072SDavid du Colombier 			}
276*a6a9e072SDavid du Colombier 		}
277*a6a9e072SDavid du Colombier 		/* move p up one to avoid pointing to null at end of p2 */
278*a6a9e072SDavid du Colombier 		if(*p)
279*a6a9e072SDavid du Colombier 			p++;
280*a6a9e072SDavid du Colombier 		*p2 = 0;
281*a6a9e072SDavid du Colombier 	}
282*a6a9e072SDavid du Colombier 	argv[i] = 0;
283*a6a9e072SDavid du Colombier 
284*a6a9e072SDavid du Colombier 	return i;
285*a6a9e072SDavid du Colombier }
286*a6a9e072SDavid du Colombier 
287