home *** CD-ROM | disk | FTP | other *** search
/ ftp.madoka.org / 2014.12.ftp.madoka.org.tar / ftp.madoka.org / pub / irchat-pj / 2.5 / irchat-pj-2.5.6p.tar.gz / irchat-pj-2.5.6p.tar / irchat-pj-2.5.6p / dcc.c < prev    next >
C/C++ Source or Header  |  2000-11-05  |  16KB  |  663 lines

  1. /*
  2. ** dcc.c (for irchat-jp)
  3. ** Copyright (C) 1995,1996,1998,1999 KIKUCHI Takahiro
  4. **
  5. ** Author:        KIKUCHI Takahiro <kick@kyoto.wide.ad.jp>
  6. ** Created:       Mar 19, 1995
  7. ** Last Modified: Jul  7, 1999
  8. */
  9.  
  10. /*
  11. ** dcc.c for irchat-pj by irchat-PJ Project
  12. ** - modified for Linux GLIBC by simm@irc.fan.gr.jp
  13. ** - modified for Microsoft Windows by quiver@tky3.3web.ne.jp
  14. ** - modified for OS/2 Warp by yuu@cb3.so-net.ne.jp
  15. ** - merge by simm@irc.fan.gr.jp, Sun, 20 Feb 2000 03:50:01 +0900
  16. **
  17. ** $Id: dcc.c,v 1.5 2000/11/05 15:01:53 simm Exp $
  18. */
  19.  
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <sys/param.h>
  23. #include <sys/socket.h>
  24. #include <sys/file.h>
  25. #include <netinet/in.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <fcntl.h>
  29. #include <netdb.h>
  30. #ifdef    AIX
  31. # include <sys/select.h>
  32. #endif
  33. #ifdef    linux
  34. # ifndef __GLIBC__
  35. #  include <linux/time.h>
  36. # endif
  37. #endif
  38. #ifdef    SOCKS
  39. # include <socks.h>
  40. #endif
  41.  
  42. #ifndef O_BINARY
  43. #define O_BINARY (0)
  44. #endif
  45.  
  46. #ifdef USE_PTHREAD
  47. # define PTHREAD_KERNEL
  48. # include <pthread.h>
  49. # include <signal.h>
  50. # include <errno.h>
  51.   void *wait_resume();
  52. #endif
  53.  
  54. #define DCC_NORESUME 0
  55. #define DCC_RESUME   1
  56.  
  57.  
  58. long position = 0;
  59.  
  60. int main(argc, argv)
  61. int argc;
  62. char **argv;
  63. {
  64.     char *command, *type, *action;
  65.     int status = 1;
  66.     extern u_long atoul();
  67.     
  68. #ifdef __EMX__             /*  for emx OS/2    */
  69.    _fsetmode(stdout,"b");  /* stdout is binary */
  70.    _fsetmode(stderr,"b");  /* stderr is binary */
  71. #endif
  72.  
  73.     command = *argv++, argc--;
  74.     if (argc < 2) {
  75.     printf("DCC ERROR Not enough parameters\n");
  76.     fprintf(stderr, "Usage: %s <type> <command> <arg>...\n", command);
  77.     exit(1);
  78.     }
  79.  
  80.     type = *argv++, argc--;
  81.     action = *argv++, argc--;
  82.  
  83.     if (!stricmp(type, "check")) {
  84. #ifdef USE_PTHREAD
  85.     printf("DCC RESUME OK\n");
  86.     return 0;
  87. #else
  88.     printf("DCC RESUME NG\n");
  89.     return 1;
  90. #endif    
  91.     } else if (!stricmp(type, "file")) {
  92.     if (!stricmp(action, "send")) {
  93.         if (argc == 1) {
  94.         status = file_send(argv[0], 0, 0);
  95.         } else if (argc == 2) {
  96.         status = file_send(argv[0], atoi(argv[1]), 0);
  97.         } else if (argc == 3) {
  98.         status = file_send(argv[0], atoi(argv[1]), argv[2]);
  99.         } else {
  100.         printf("DCC ERROR Wrong number of parameters\n");
  101.         fprintf(stderr,
  102.             "Usage: %s file send <filename> <port> <ircserver>\n",
  103.             command);
  104.         status = 1;
  105.         }
  106.     } else if (!stricmp(action, "get")) {
  107.         if (argc == 4 || argc == 5) {
  108.         status = file_get(atoul(argv[0]), atoi(argv[1]),
  109.                   atoi(argv[2]), argv[3],"",DCC_NORESUME);
  110.         } else {
  111.         printf("DCC ERROR Wrong number of parameters\n");
  112.         fprintf(stderr,
  113.             "Usage: %s file get <addr> <port> <size> <filename>\n",
  114.             command);
  115.         status = 1;
  116.         }
  117.     } else if (!stricmp(action, "rget")) {
  118.       if (argc == 5) {
  119.         status = file_get(atoul(argv[0]),atoi(argv[1]),
  120.                   atoi(argv[2]),argv[3],argv[4],DCC_RESUME);
  121.       } else if (argc == 4) {
  122.         status = file_get(atoul(argv[0]),atoi(argv[1]),
  123.                   atoi(argv[2]),argv[3],argv[3],DCC_RESUME);
  124.       } else {
  125.         printf("DCC ERROR Wrong number of parameters\n");
  126.         fprintf(stderr,
  127.             "Usage: %s file rget <addr> <port> <size> <filename> <filename2> \n",
  128.             command);
  129.         status = 1;
  130.       }
  131.     } else {
  132.         printf("DCC ERROR Unsupported command %s %s\n", type, action);
  133.         status = 1;
  134.     }
  135.     } else if (!stricmp(type, "chat")) {
  136.     if (!stricmp(action, "listen")) {
  137.         if (argc == 0) {
  138.         status = chat_listen(0, 0);
  139.         } else if (argc == 1) {
  140.         status = chat_listen(atoi(argv[0]), 0);
  141.         } else if (argc == 2) {
  142.         status = chat_listen(atoi(argv[0]), argv[1]);
  143.         } else {
  144.         printf("DCC ERROR Wrong number of parameters\n");
  145.         fprintf(stderr, "Usage: %s chat listen <port> <ircserver>\n",
  146.             command);
  147.         status = 1;
  148.         }
  149.     } else if (!stricmp(action, "connect")) {
  150.         if (argc == 2) {
  151.         status = chat_connect(atoul(argv[0]), atoi(argv[1]));
  152.         } else {
  153.         printf("DCC ERROR Wrong number of parameters\n");
  154.         fprintf(stderr, "Usage: %s chat connect <addr> <port>\n",
  155.             command);
  156.         status = 1;
  157.         }
  158.     } else {
  159.         printf("DCC ERROR Unsupported command %s %s\n", type, action);
  160.         status = 1;
  161.     }
  162.     } else if (!stricmp(type, "tcp")) {
  163.     if (!stricmp(action, "connect")) {
  164.         if (argc == 2) {
  165.         status = tcp_connect(argv[0], argv[1]);
  166.         } else {
  167.         printf("DCC ERROR Wrong number of parameters\n");
  168.         fprintf(stderr, "Usage: %s chat connect <addr> <port>\n",
  169.             command);
  170.         status = 1;
  171.         }
  172.     } else {
  173.         printf("DCC ERROR Unsupported command %s %s\n", type, action);
  174.         status = 1;
  175.     }
  176.     } else {
  177.     printf("DCC ERROR Unsupported command %s\n", type);
  178.     status = 1;
  179.     }
  180.     if (status) {
  181.     sleep(3);
  182.     }
  183.     exit(status);
  184. }
  185.  
  186. #ifdef _WIN32
  187. u_long getmyaddr(ircserver)
  188. char *ircserver;
  189. {
  190.         int i;
  191.         struct hostent *hp;
  192.         char hostname[50];
  193.         struct in_addr addr;
  194.  
  195.         gethostname(hostname, sizeof(hostname));
  196.         hp = gethostbyname(hostname);
  197.         for (i = 0; hp->h_addr_list[i] != 0; ++i);
  198.         memcpy(&addr, hp->h_addr_list[i-1], sizeof(struct in_addr));
  199.     return ntohl(addr.s_addr);
  200. }
  201. #else
  202. u_long getmyaddr(ircserver)
  203. char *ircserver;
  204. {
  205.     int i, len, dummy;
  206.     u_long addr;
  207.     char *p;
  208.     struct hostent *hp;
  209.     struct sockaddr_in server, client;
  210.  
  211.     addr = 0xc6290004;                /* dummy addr --- rootA */
  212.     if (ircserver && (hp = gethostbyname(ircserver)) != NULL) {
  213.     addr = ntohl(((struct in_addr *)hp->h_addr_list[0])->s_addr);
  214.     }
  215.     if ((dummy = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  216.     printf("DCC ERROR Cannot create socket\n");
  217.     return -1;
  218.     }
  219.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  220.     server.sin_family = AF_INET;
  221.     server.sin_addr.s_addr = htonl(addr);
  222.     server.sin_port = htons(7);            /* dummy port --- echo */
  223.     if (connect(dummy, (struct sockaddr *)&server, sizeof(server)) < 0) {
  224.     printf("DCC ERROR Cannot connect socket\n");
  225.     return -1;
  226.     }
  227.     len = sizeof(client);
  228.     if (getsockname(dummy, (struct sockaddr *)&client, &len) < 0) {
  229.     printf("DCC ERROR Cannot getsockname\n");
  230.     return -1;
  231.     }
  232.     close(dummy);
  233.     return ntohl(client.sin_addr.s_addr);
  234. }
  235. #endif
  236.  
  237. int dcc_listen(paddr, pport, ircserver)
  238. u_long *paddr;
  239. u_short *pport;
  240. char *ircserver;
  241. {
  242.     int i, s, len;
  243.     char *p;
  244.     struct sockaddr_in server;
  245.  
  246.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  247.     printf("DCC ERROR Cannot create socket\n");
  248.     return -1;
  249.     }
  250.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  251.     server.sin_family = AF_INET;
  252.     server.sin_addr.s_addr = htonl(getmyaddr(ircserver));
  253.     server.sin_port = htons(*pport);
  254.     while (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
  255.     if (!*pport) {
  256.         printf("DCC ERROR Cannot bind socket\n");
  257.         return -1;
  258.     }
  259.     server.sin_port = htons(++(*pport));
  260.     }
  261.     if (listen(s, 1) < 0) {
  262.     printf("DCC ERROR Cannot listen socket\n");
  263.     return -1;
  264.     }
  265.     len = sizeof(server);
  266.     if (getsockname(s, (struct sockaddr *)&server, &len) < 0) {
  267.     printf("DCC ERROR Cannot getsockname\n");
  268.     return -1;
  269.     }    
  270.     *pport = ntohs(server.sin_port);
  271.     *paddr = ntohl(server.sin_addr.s_addr);
  272.  
  273.     return s;
  274. }
  275.  
  276. int dcc_connect(addr, port)
  277. u_long addr;
  278. u_short port;
  279. {
  280.     int i, remote;
  281.     char *p;
  282.     struct sockaddr_in server;
  283.  
  284.     if ((remote = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  285.     printf("DCC ERROR Cannot create socket\n");
  286.     return -1;
  287.     }
  288.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  289.     server.sin_family = AF_INET;
  290.     server.sin_addr.s_addr = htonl(addr);
  291.     server.sin_port = htons(port);
  292.     if (connect(remote, (struct sockaddr *)&server, sizeof(server)) < 0) {
  293.     printf("DCC ERROR Cannot connect %u/%d\n", addr, port);
  294.     return -1;
  295.     }
  296.     return remote;
  297. }
  298.  
  299. u_long atoul(str)
  300. char *str;
  301. {
  302.     u_long val = 0;
  303.  
  304.     while (*str) {
  305.     val = val * 10 + *str - '0';
  306.     str++;
  307.     }
  308.     return val;
  309. }
  310.  
  311. u_long dottoul(str)
  312. char *str;
  313. {
  314.     u_long val, v;
  315.  
  316.     for (val = v = 0; *str; str++) {
  317.     if (*str == '.') {
  318.         val = val * 256 + v;
  319.         v = 0;
  320.     } else {
  321.         v = v * 10 + *str - '0';
  322.     }
  323.     }
  324.     val = val * 256 + v;
  325.     return val;
  326. }
  327.  
  328. int file_send(filename, port, ircserver)
  329. char *filename;
  330. u_short port;
  331. char *ircserver;
  332. {
  333.     int i, file, size, s, remote, len, count = 0;
  334.     u_long addr;
  335.     struct stat statbuf;
  336.     u_long done = 0;
  337.     u_long report;
  338.     char buf[4096];
  339.  
  340. #ifdef USE_PTHREAD
  341.     pthread_t thread;
  342. # ifdef ENABLE_PTHREAD_ATTR
  343.     pthread_attr_t th_attr;
  344. # endif
  345. #endif
  346.  
  347.     if ((file = open(filename, O_RDONLY|O_BINARY)) < 0) {
  348.     printf("DCC ERROR Cannot open file %s\n", filename);
  349.     return 1;
  350.     }
  351.     if (fstat(file, &statbuf) < 0) {
  352.     printf("DCC ERROR Cannot stat file %s\n", filename);
  353.     return 1;
  354.     }
  355.     size = statbuf.st_size;
  356.  
  357.     if ((s = dcc_listen(&addr, &port, ircserver)) < 0) {
  358.     /* error report in dcc_listen */
  359.     return 1;
  360.     }
  361.     /* 'Setting -> 'Waiting (send DCC SEND to remote user) */
  362.     printf("DCC SEND %u %d %d\n", addr, port, size);
  363.  
  364. #ifdef USE_PTHREAD   
  365.     /* Create Thread wait_resume() : Waiting DCC Resume    */
  366.     position = 0;
  367. # ifdef ENABLE_PTHREAD_ATTR
  368.     if(pthread_attr_init(&th_attr));
  369.     pthread_attr_setdetachstate(&th_attr,PTHREAD_CREATE_DETACHED);
  370.     if(pthread_create(&thread,&th_attr,wait_resume,NULL))
  371. # else
  372.     if(pthread_create(&thread,NULL,wait_resume,NULL))
  373. # endif
  374.       printf("DCC WARNING Not Support Send Resume\n");
  375. #endif
  376.  
  377.     remote = accept(s, (struct sockaddr *) 0, (int *) 0);
  378.     close(s);
  379.     /* 'Waiting -> 'Sending (accepted from remote user) */
  380.     printf("DCC SENDING\n");
  381.  
  382. #ifdef USE_PTHREAD
  383.     /* Interrupt Thread : wait_resume() */
  384. # ifndef USE_PTHREAD_KILL
  385.     pthread_cancel(thread);
  386. # else
  387.     if(pthread_kill(thread,0) != ESRCH) pthread_kill(thread,SIGINT);
  388. # endif /* USE_PTHREAD_KILL */
  389. # ifdef ENABLE_PTHREAD_ATTR
  390.     pthread_attr_destroy(&th_attr);
  391. # endif /* ENABLE_PTHREAD_ATTR*/
  392.     /* Resume Point position by wait_resume() */
  393.     if(done != position) done = lseek(file,position,SEEK_SET);
  394. #endif /* USE_PTHREAD */
  395.  
  396.     while ((len = read(file, buf, sizeof(buf))) > 0) {
  397.     write(remote, buf, len);
  398.     done += len;
  399.     if (++count == 16) {
  400.         count = 0;
  401.         while (read(remote, &report, sizeof(u_long)) > 0 &&
  402.            ntohl(report) != done);
  403.         printf("DCC REPORT %s %d%% (%d/%d bytes) sent\n",
  404.            filename, 100 * done / size, done, size);
  405.     }
  406.     }
  407.     while (read(remote, &report, sizeof(u_long)) > 0 &&
  408.        ntohl(report) != done);
  409.  
  410.     /* 'Sending -> end */
  411.     close(remote);
  412.     close(file);
  413.     return 0;
  414. }
  415.  
  416. int file_get(addr, port, size, filename,filename2,resume)
  417. u_long addr;
  418. u_short port;
  419. int size;
  420. char *filename;
  421. char *filename2;
  422. u_short resume;
  423. {
  424.     int i, remote, file, len, oflag, toread, count = 0;
  425.     u_short rport;
  426.     u_long done = 0;
  427.     u_long report;
  428.     char dcc[32],cmd[32],fn[256],buf[4096];
  429.     
  430.     oflag = O_WRONLY|O_BINARY|O_CREAT;
  431.     if(resume == DCC_NORESUME) oflag = oflag | O_TRUNC;
  432.     rport = port;
  433.  
  434.     if ((file = open(filename,oflag, 0600)) < 0) {
  435.     printf("DCC ERROR1 Cannot open file %s\n", filename);
  436.     return 1;
  437.     }
  438.     if(resume == DCC_RESUME) {
  439.       position = 0;
  440.       done = lseek(file,0,SEEK_END);
  441.       printf("DCC RESUME %s %d %d\n",filename2,port,done);
  442.       fgets(buf,sizeof(buf),stdin);
  443.       if((sscanf(buf,"%s %s %s %d %d",dcc,cmd,fn,&rport,&position) != 5)
  444.      || stricmp(dcc,"DCC") || stricmp(cmd,"ACCEPT")){
  445.     printf("%s,%s,%s,%d,%d\n",dcc,cmd,fn,port,position);
  446.     printf("DCC ERROR Unsupported command %s\n",buf);
  447.     return 1;
  448.       }
  449.       if(done != position) done = lseek(file,position,SEEK_SET);
  450.     }
  451.  
  452.  
  453.     if ((remote = dcc_connect(addr, rport)) < 0) {
  454.     /* error report in dcc_connect */
  455.     return 1;
  456.     }
  457.     /* 'Connect -> 'Getting (connected to remote user) */
  458.     printf("DCC GETTING\n");
  459.  
  460.     toread = sizeof(buf);
  461.     while (size - done > 0) {
  462.     if (toread > size - done) {
  463.         toread = size - done;
  464.     }
  465.     if ((len = read(remote, buf, toread)) < 0) {
  466.         printf("DCC ERROR read error %s\n", filename);
  467.         return 1;
  468.     }
  469.     write(file, buf, len);
  470.     done += len;
  471.     report = htonl(done);
  472.     write(remote, &report, sizeof(report));
  473.     if (++count == 16) {
  474.         count = 0;
  475.         printf("DCC REPORT %s %d%% (%d/%d bytes) received\n",
  476.            filename, 100 * done / size, done, size);
  477.     }
  478.     }
  479.  
  480.     /* 'Getting -> end */
  481.     close(remote);
  482.     close(file);
  483.     return 0;
  484. }
  485.  
  486. int chat_listen(port, ircserver)
  487. u_short port;
  488. char *ircserver;
  489. {
  490.     u_long addr;
  491.     int s, remote;
  492.  
  493.     if ((s = dcc_listen(&addr, &port, ircserver)) < 0) {
  494.     return 1;
  495.     }
  496.     /* 'Setting -> 'Waiting (send DCC CHAT to remote user) */
  497.     printf("DCC CHAT %u %d\n", addr, port);
  498.  
  499.     remote = accept(s, (struct sockaddr *) 0, (int *) 0);
  500.     close(s);
  501.     /* 'Waiting -> 'Active (accepted from remote user) */
  502.     printf("DCC CHATTING\n");
  503.     return loop(remote);
  504. }
  505.  
  506. int chat_connect(addr, port)
  507. u_long addr;
  508. u_short port;
  509. {
  510.     int remote;
  511.  
  512.     if ((remote = dcc_connect(addr, port)) < 0) {
  513.     return 1;
  514.     }
  515.     /* 'Connect -> 'Active (connected to remote user) */
  516.     printf("DCC CHATTING\n");
  517.     return loop(remote);
  518. }
  519.  
  520. int loop(remote)
  521. int remote;
  522. {
  523.     int n, len, cnt;
  524.     char *ptr, buf[1024];
  525.     fd_set rfds;
  526.  
  527.     while (1) {
  528.     FD_ZERO(&rfds);
  529.     FD_SET(0, &rfds);
  530.     FD_SET(remote, &rfds);
  531.     if ((n = select(FD_SETSIZE, &rfds, NULL, NULL, NULL)) == -1) {
  532.         continue;
  533.     }
  534.     if (FD_ISSET(0, &rfds)) {
  535.         if ((len = read(0, buf, sizeof(buf))) <= 0) {
  536.         close(0);
  537.         close(remote);
  538.         if (len == 0) {
  539.             return 0;
  540.         } else {
  541.             return 1;
  542.         }
  543.         }
  544.         for (ptr = buf; len > 0; ptr+= cnt, len -= cnt) {
  545.         if ((cnt = write(remote, ptr, len)) < 0) {
  546.             close(0);
  547.             close(remote);
  548.             return 1;
  549.         }
  550.         }
  551.     }
  552.     if (FD_ISSET(remote, &rfds)) {
  553.         if ((len = read(remote, buf, sizeof(buf))) <= 0) {
  554.         close(0);
  555.         close(remote);
  556.         if (len == 0) {
  557.             return 0;
  558.         } else {
  559.             return 1;
  560.         }
  561.         }
  562.         for (ptr = buf; len > 0; ptr+= cnt, len -= cnt) {
  563.         if ((cnt = write(0, ptr, len)) < 0) {
  564.             close(0);
  565.             close(remote);
  566.             return 1;
  567.         }
  568.         }
  569.     }
  570.     }
  571. }
  572.  
  573. int tcp_connect(straddr, strport)
  574. char *straddr, *strport;
  575. {
  576.     int remote;
  577.   
  578. #ifdef INET6
  579.     int eai;
  580.     struct addrinfo hints, *ai;
  581.  
  582.     memset(&hints, 0, sizeof(hints));
  583.     hints.ai_family = AF_UNSPEC;
  584.     hints.ai_socktype = SOCK_STREAM;
  585.     if ((eai = getaddrinfo(straddr, strport, &hints, &ai)) != 0) {
  586.         printf("ERROR :Closing Link: [*@*] (Cannot resolve %s: %s)\n",
  587.            straddr, gai_strerror(eai));
  588.         return 0;
  589.     }
  590.     if ((remote = socket(ai->ai_family, SOCK_STREAM, 0)) < 0) {
  591.         printf("ERROR :Closing Link: [*@*] (Cannot create socket)\n");
  592.     return 0;
  593.     }
  594.     if (connect(remote, ai->ai_addr, ai->ai_addrlen) < 0) {
  595.         printf("ERROR :Closing Link: [*@*] (Cannot connect to %s/%s)\n",
  596.            straddr, strport);
  597.     return 0;
  598.     }
  599. #else
  600.     int i;
  601.     u_long addr;
  602.     char *p;
  603.     struct hostent *hp;
  604.     struct sockaddr_in server;
  605.  
  606.     if (*straddr >= '0' && *straddr <= '9') {
  607.         addr = dottoul(straddr);
  608.     } else if ((hp = gethostbyname(straddr)) != NULL) {
  609.     addr = ntohl(((struct in_addr *)hp->h_addr_list[0])->s_addr);
  610.     } else {
  611.         printf("ERROR :Closing Link: [*@*] (Cannot resolve %s)\n", straddr);
  612.     return 0;
  613.     }
  614.     if ((remote = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  615.         printf("ERROR :Closing Link: [*@*] (Cannot create socket)\n");
  616.     return 0;
  617.     }
  618.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  619.     server.sin_family = AF_INET;
  620.     server.sin_addr.s_addr = htonl(addr);
  621.     server.sin_port = htons(atoi(strport));
  622.     if (connect(remote, (struct sockaddr *)&server, sizeof(server)) < 0) {
  623.         printf("ERROR :Closing Link: [*@*] (Cannot connect to %s/%s)\n",
  624.            straddr, strport);
  625.     return 0;
  626.     }
  627. #endif
  628.  
  629.     return loop(remote);
  630. }
  631.  
  632. #ifdef USE_PTHREAD
  633. void *wait_resume()
  634. {
  635.   char dcc[32],cmd[32],fn[256],buf[1024];
  636.   u_short port;
  637.   long    tposition;
  638.   fgets(buf,sizeof(buf),stdin);
  639.   if((sscanf(buf,"%s %s %s %d %d",dcc,cmd,fn,&port,&tposition) != 5)
  640.      || stricmp(dcc,"DCC") || stricmp(cmd,"RESUME") || (strlen(fn) == 0)){
  641.     printf("DCC ERROR Unsupported command %s\n",buf);
  642.     exit(1);
  643.   }
  644.   position = tposition;
  645.   printf("DCC ACCEPT %s %d %d\n",fn,port,position);
  646.   pthread_exit(0);
  647. }
  648. #endif
  649.  
  650. int stricmp (const char *string1, const char *string2)
  651. {
  652.   int d;
  653.  
  654.   for (;;)
  655.     {
  656.       d = tolower ((unsigned char)*string1)
  657.         - tolower ((unsigned char)*string2);
  658.       if (d != 0 || *string1 == 0 || *string2 == 0)
  659.         return d;
  660.       ++string1; ++string2;
  661.     }
  662. }
  663.