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