winplumb.c 4.9 KB

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