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