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 287