winplumb.c 5.3 KB

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