]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/unix/winplumb.c
kbdfs: simplfy
[plan9front.git] / sys / src / cmd / unix / winplumb.c
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
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
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
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
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
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
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
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
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
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