home *** CD-ROM | disk | FTP | other *** search
/ ftp.madoka.org / 2014.12.ftp.madoka.org.tar / ftp.madoka.org / pub / irchat-pj / irchat-pj-2.4.24.22.tar.gz / irchat-pj-2.4.24.22.tar / irchat-pj-2.4.24.22 / dcc / dcc.c
C/C++ Source or Header  |  2000-01-24  |  13KB  |  529 lines

  1. /*
  2. ** dcc.c (for irchat-2.4jp)
  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: Jan 30, 1999
  8. **
  9. ** Modified for Linux GLIBC: Jan 12, 1999 (for 2.4jp23g dcc.c)
  10. ** by SHIMADA Mitsunobu <simm@irc.fan.gr.jp>
  11. */
  12.  
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <sys/param.h>
  16. #include <sys/socket.h>
  17. #include <sys/file.h>
  18. #include <netinet/in.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <netdb.h>
  22. #ifdef    AIX
  23. # include <sys/select.h>
  24. #endif
  25. #ifdef    linux
  26. #ifndef __GLIBC__
  27. # include <linux/time.h>
  28. #endif
  29. #endif
  30. #ifdef    SOCKS
  31. # include <socks.h>
  32. #endif
  33.  
  34. #ifndef O_BINARY
  35. #define O_BINARY (0)
  36. #endif
  37.  
  38. int main(argc, argv)
  39. int argc;
  40. char **argv;
  41. {
  42.     char *command, *type, *action;
  43.     int status = 1;
  44.     extern u_long atoul();
  45.     
  46. #ifdef __EMX__             /*  for emx OS/2    */
  47.    _fsetmode(stdout,"b");  /* stdout is binary */
  48.    _fsetmode(stderr,"b");  /* stderr is binary */
  49. #endif
  50.  
  51.     command = *argv++, argc--;
  52.     if (argc < 2) {
  53.     printf("DCC ERROR Not enough parameters\n");
  54.     fprintf(stderr, "Usage: %s <type> <command> <arg>...\n", command);
  55.     exit(1);
  56.     }
  57.  
  58.     type = *argv++, argc--;
  59.     action = *argv++, argc--;
  60.  
  61.     if (!strcmp(type, "file")) {
  62.     if (!strcmp(action, "send")) {
  63.         if (argc == 1) {
  64.         status = file_send(argv[0], 0, 0);
  65.         } else if (argc == 3) {
  66.         status = file_send(argv[0], atoi(argv[1]), argv[2]);
  67.         } else {
  68.         printf("DCC ERROR Wrong number of parameters\n");
  69.         fprintf(stderr,
  70.             "Usage: %s file send <filename> <port> <ircserver>\n",
  71.             command);
  72.         status = 1;
  73.         }
  74.     } else if (!strcmp(action, "get")) {
  75.         if (argc == 4) {
  76.         status = file_get(atoul(argv[0]), atoi(argv[1]),
  77.                   atoi(argv[2]), argv[3]);
  78.         } else {
  79.         printf("DCC ERROR Wrong number of parameters\n");
  80.         fprintf(stderr,
  81.             "Usage: %s file get <addr> <port> <size> <filename>\n",
  82.             command);
  83.         status = 1;
  84.         }
  85.     } else {
  86.         printf("DCC ERROR Unsupported command %s %s\n", type, action);
  87.         status = 1;
  88.     }
  89.     } else if (!strcmp(type, "chat")) {
  90.     if (!strcmp(action, "listen")) {
  91.         if (argc == 0) {
  92.         status = chat_listen(0, 0);
  93.         } else if (argc == 2) {
  94.         status = chat_listen(atoi(argv[0]), argv[1]);
  95.         } else {
  96.         printf("DCC ERROR Wrong number of parameters\n");
  97.         fprintf(stderr, "Usage: %s chat listen <port> <ircserver>\n",
  98.             command);
  99.         status = 1;
  100.         }
  101.     } else if (!strcmp(action, "connect")) {
  102.         if (argc == 2) {
  103.         status = chat_connect(atoul(argv[0]), atoi(argv[1]));
  104.         } else {
  105.         printf("DCC ERROR Wrong number of parameters\n");
  106.         fprintf(stderr, "Usage: %s chat connect <addr> <port>\n",
  107.             command);
  108.         status = 1;
  109.         }
  110.     } else {
  111.         printf("DCC ERROR Unsupported command %s %s\n", type, action);
  112.         status = 1;
  113.     }
  114.     } else if (!strcmp(type, "tcp")) {
  115.     if (!strcmp(action, "connect")) {
  116.         if (argc == 2) {
  117.         status = tcp_connect(argv[0], argv[1]);
  118.         } else {
  119.         printf("DCC ERROR Wrong number of parameters\n");
  120.         fprintf(stderr, "Usage: %s chat connect <addr> <port>\n",
  121.             command);
  122.         status = 1;
  123.         }
  124.     } else {
  125.         printf("DCC ERROR Unsupported command %s %s\n", type, action);
  126.         status = 1;
  127.     }
  128.     } else {
  129.     printf("DCC ERROR Unsupported command %s\n", type);
  130.     status = 1;
  131.     }
  132.     if (status) {
  133.     sleep(3);
  134.     }
  135.     exit(status);
  136. }
  137.  
  138. #ifdef _WIN32
  139. u_long getmyaddr(ircserver)
  140. char *ircserver;
  141. {
  142.     int i;
  143.     struct hostent *hp;
  144.     char hostname[50];
  145.     struct in_addr addr;
  146.  
  147.     gethostname(hostname, sizeof(hostname));
  148.     hp = gethostbyname(hostname);
  149.     for (i = 0; hp->h_addr_list[i] != 0; ++i);
  150.     memcpy(&addr, hp->h_addr_list[i-1], sizeof(struct in_addr));
  151.     return ntohl(addr.s_addr);
  152. }
  153. #else
  154. u_long getmyaddr(ircserver)
  155. char *ircserver;
  156. {
  157.     int i, len, dummy;
  158.     u_long addr;
  159.     char *p;
  160.     struct hostent *hp;
  161.     struct sockaddr_in server, client;
  162.  
  163.     addr = 0xc6290004;                /* dummy addr --- rootA */
  164.     if (ircserver && (hp = gethostbyname(ircserver)) != NULL) {
  165.     addr = ntohl(((struct in_addr *)hp->h_addr_list[0])->s_addr);
  166.     }
  167.     if ((dummy = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  168.     printf("DCC ERROR Cannot create socket\n");
  169.     return -1;
  170.     }
  171.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  172.     server.sin_family = AF_INET;
  173.     server.sin_addr.s_addr = htonl(addr);
  174.     server.sin_port = htons(7);            /* dummy port --- echo */
  175.     if (connect(dummy, (struct sockaddr *)&server, sizeof(server)) < 0) {
  176.     printf("DCC ERROR Cannot connect socket\n");
  177.     return -1;
  178.     }
  179.     len = sizeof(client);
  180.     if (getsockname(dummy, (struct sockaddr *)&client, &len) < 0) {
  181.     printf("DCC ERROR Cannot getsockname\n");
  182.     return -1;
  183.     }
  184.     close(dummy);
  185.     return ntohl(client.sin_addr.s_addr);
  186. }
  187. #endif
  188.  
  189. int dcc_listen(paddr, pport, ircserver)
  190. u_long *paddr;
  191. u_short *pport;
  192. char *ircserver;
  193. {
  194.     int i, s, len;
  195.     char *p;
  196.     struct sockaddr_in server;
  197.  
  198.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  199.     printf("DCC ERROR Cannot create socket\n");
  200.     return -1;
  201.     }
  202.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  203.     server.sin_family = AF_INET;
  204.     server.sin_addr.s_addr = htonl(getmyaddr(ircserver));
  205.     server.sin_port = htons(*pport);
  206.     while (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
  207.     if (!*pport) {
  208.         printf("DCC ERROR Cannot bind socket\n");
  209.         return -1;
  210.     }
  211.     server.sin_port = htons(++(*pport));
  212.     }
  213.     if (listen(s, 1) < 0) {
  214.     printf("DCC ERROR Cannot listen socket\n");
  215.     return -1;
  216.     }
  217.     len = sizeof(server);
  218.     if (getsockname(s, (struct sockaddr *)&server, &len) < 0) {
  219.     printf("DCC ERROR Cannot getsockname\n");
  220.     return -1;
  221.     }    
  222.     *pport = ntohs(server.sin_port);
  223.     *paddr = ntohl(server.sin_addr.s_addr);
  224.  
  225.     return s;
  226. }
  227.  
  228. int dcc_connect(addr, port)
  229. u_long addr;
  230. u_short port;
  231. {
  232.     int i, remote;
  233.     char *p;
  234.     struct sockaddr_in server;
  235.  
  236.     if ((remote = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  237.     printf("DCC ERROR Cannot create socket\n");
  238.     return -1;
  239.     }
  240.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  241.     server.sin_family = AF_INET;
  242.     server.sin_addr.s_addr = htonl(addr);
  243.     server.sin_port = htons(port);
  244.     if (connect(remote, (struct sockaddr *)&server, sizeof(server)) < 0) {
  245.     printf("DCC ERROR Cannot connect %u/%d\n", addr, port);
  246.     return -1;
  247.     }
  248.     return remote;
  249. }
  250.  
  251. u_long atoul(str)
  252. char *str;
  253. {
  254.     u_long val = 0;
  255.  
  256.     while (*str) {
  257.     val = val * 10 + *str - '0';
  258.     str++;
  259.     }
  260.     return val;
  261. }
  262.  
  263. u_long dottoul(str)
  264. char *str;
  265. {
  266.     u_long val, v;
  267.  
  268.     for (val = v = 0; *str; str++) {
  269.     if (*str == '.') {
  270.         val = val * 256 + v;
  271.         v = 0;
  272.     } else {
  273.         v = v * 10 + *str - '0';
  274.     }
  275.     }
  276.     val = val * 256 + v;
  277.     return val;
  278. }
  279.  
  280. int file_send(filename, port, ircserver)
  281. char *filename;
  282. u_short port;
  283. char *ircserver;
  284. {
  285.     int file, size, s, remote, len, count = 0;
  286.     u_long addr;
  287.     struct stat statbuf;
  288.     u_long done = 0;
  289.     u_long report;
  290.     char buf[4096];
  291.  
  292.     if ((file = open(filename, O_RDONLY|O_BINARY)) < 0) {
  293.     printf("DCC ERROR Cannot open file %s\n", filename);
  294.     return 1;
  295.     }
  296.     if (fstat(file, &statbuf) < 0) {
  297.     printf("DCC ERROR Cannot stat file %s\n", filename);
  298.     return 1;
  299.     }
  300.     size = statbuf.st_size;
  301.  
  302.     if ((s = dcc_listen(&addr, &port, ircserver)) < 0) {
  303.     /* error report in dcc_listen */
  304.     return 1;
  305.     }
  306.     /* 'Setting -> 'Waiting (send DCC SEND to remote user) */
  307.     printf("DCC SEND %u %d %d\n", addr, port, size);
  308.  
  309.     remote = accept(s, (struct sockaddr *) 0, (int *) 0);
  310.     close(s);
  311.     /* 'Waiting -> 'Sending (accepted from remote user) */
  312.     printf("DCC SENDING\n");
  313.  
  314.     while ((len = read(file, buf, sizeof(buf))) > 0) {
  315.     write(remote, buf, len);
  316.     done += len;
  317.     if (++count == 16) {
  318.         count = 0;
  319.         while (read(remote, &report, sizeof(u_long)) > 0 &&
  320.            ntohl(report) != done);
  321.         printf("DCC REPORT %s %d%% (%d/%d bytes) sent\n",
  322.            filename, 100 * done / size, done, size);
  323.     }
  324.     }
  325.     while (read(remote, &report, sizeof(u_long)) > 0 &&
  326.        ntohl(report) != done);
  327.  
  328.     /* 'Sending -> end */
  329.     close(remote);
  330.     close(file);
  331.     return 0;
  332. }
  333.  
  334. int file_get(addr, port, size, filename)
  335. u_long addr;
  336. u_short port;
  337. int size;
  338. char *filename;
  339. {
  340.     int remote, file, len, toread, count = 0;
  341.     u_long done = 0;
  342.     u_long report;
  343.     char buf[4096];
  344.  
  345.     if ((file = open(filename, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0600)) < 0) {
  346.     printf("DCC ERROR1 Cannot open file %s\n", filename);
  347.     return 1;
  348.     }
  349.  
  350.     if ((remote = dcc_connect(addr, port)) < 0) {
  351.     /* error report in dcc_connect */
  352.     return 1;
  353.     }
  354.     /* 'Connect -> 'Getting (connected to remote user) */
  355.     printf("DCC GETTING\n");
  356.  
  357.     toread = sizeof(buf);
  358.     while (size - done > 0) {
  359.     if (toread > size - done) {
  360.         toread = size - done;
  361.     }
  362.     if ((len = read(remote, buf, toread)) < 0) {
  363.         printf("DCC ERROR read error %s\n", filename);
  364.         return 1;
  365.     }
  366.     write(file, buf, len);
  367.     done += len;
  368.     report = htonl(done);
  369.     write(remote, &report, sizeof(report));
  370.     if (++count == 16) {
  371.         count = 0;
  372.         printf("DCC REPORT %s %d%% (%d/%d bytes) received\n",
  373.            filename, 100 * done / size, done, size);
  374.     }
  375.     }
  376.  
  377.     /* 'Getting -> end */
  378.     close(remote);
  379.     close(file);
  380.     return 0;
  381. }
  382.  
  383. int chat_listen(port, ircserver)
  384. u_short port;
  385. char *ircserver;
  386. {
  387.     u_long addr;
  388.     int s, remote;
  389.  
  390.     if ((s = dcc_listen(&addr, &port, ircserver)) < 0) {
  391.     return 1;
  392.     }
  393.     /* 'Setting -> 'Waiting (send DCC CHAT to remote user) */
  394.     printf("DCC CHAT %u %d\n", addr, port);
  395.  
  396.     remote = accept(s, (struct sockaddr *) 0, (int *) 0);
  397.     close(s);
  398.     /* 'Waiting -> 'Active (accepted from remote user) */
  399.     printf("DCC CHATTING\n");
  400.     return loop(remote);
  401. }
  402.  
  403. int chat_connect(addr, port)
  404. u_long addr;
  405. u_short port;
  406. {
  407.     int remote;
  408.  
  409.     if ((remote = dcc_connect(addr, port)) < 0) {
  410.     return 1;
  411.     }
  412.     /* 'Connect -> 'Active (connected to remote user) */
  413.     printf("DCC CHATTING\n");
  414.     return loop(remote);
  415. }
  416.  
  417. int loop(remote)
  418. int remote;
  419. {
  420.     int n, len, cnt;
  421.     char *ptr, buf[1024];
  422.     fd_set rfds;
  423.  
  424.     while (1) {
  425.     FD_ZERO(&rfds);
  426.     FD_SET(0, &rfds);
  427.     FD_SET(remote, &rfds);
  428.     if ((n = select(FD_SETSIZE, &rfds, NULL, NULL, NULL)) == -1) {
  429.         continue;
  430.     }
  431.     if (FD_ISSET(0, &rfds)) {
  432.         if ((len = read(0, buf, sizeof(buf))) <= 0) {
  433.         close(0);
  434.         close(remote);
  435.         if (len == 0) {
  436.             return 0;
  437.         } else {
  438.             return 1;
  439.         }
  440.         }
  441.         for (ptr = buf; len > 0; ptr+= cnt, len -= cnt) {
  442.         if ((cnt = write(remote, ptr, len)) < 0) {
  443.             close(0);
  444.             close(remote);
  445.             return 1;
  446.         }
  447.         }
  448.     }
  449.     if (FD_ISSET(remote, &rfds)) {
  450.         if ((len = read(remote, buf, sizeof(buf))) <= 0) {
  451.         close(0);
  452.         close(remote);
  453.         if (len == 0) {
  454.             return 0;
  455.         } else {
  456.             return 1;
  457.         }
  458.         }
  459.         for (ptr = buf; len > 0; ptr+= cnt, len -= cnt) {
  460.         if ((cnt = write(0, ptr, len)) < 0) {
  461.             close(0);
  462.             close(remote);
  463.             return 1;
  464.         }
  465.         }
  466.     }
  467.     }
  468. }
  469.  
  470. int tcp_connect(straddr, strport)
  471. char *straddr, *strport;
  472. {
  473.     int remote;
  474.   
  475. #ifdef INET6
  476.     int eai;
  477.     struct addrinfo hints, *ai;
  478.  
  479.     memset(&hints, 0, sizeof(hints));
  480.     hints.ai_family = AF_UNSPEC;
  481.     hints.ai_socktype = SOCK_STREAM;
  482.     if ((eai = getaddrinfo(straddr, strport, &hints, &ai)) != 0) {
  483.         printf("ERROR :Closing Link: [*@*] (Cannot resolve %s: %s)\n",
  484.            straddr, gai_strerror(eai));
  485.         return 0;
  486.     }
  487.     if ((remote = socket(ai->ai_family, SOCK_STREAM, 0)) < 0) {
  488.         printf("ERROR :Closing Link: [*@*] (Cannot create socket)\n");
  489.     return 0;
  490.     }
  491.     if (connect(remote, ai->ai_addr, ai->ai_addrlen) < 0) {
  492.         printf("ERROR :Closing Link: [*@*] (Cannot connect to %s/%s)\n",
  493.            straddr, strport);
  494.     return 0;
  495.     }
  496. #else
  497.     int i;
  498.     u_long addr;
  499.     char *p;
  500.     struct hostent *hp;
  501.     struct sockaddr_in server;
  502.  
  503.     if (*straddr >= '0' && *straddr <= '9') {
  504.         addr = dottoul(straddr);
  505.     } else if ((hp = gethostbyname(straddr)) != NULL) {
  506.     addr = ntohl(((struct in_addr *)hp->h_addr_list[0])->s_addr);
  507.     } else {
  508.         printf("ERROR :Closing Link: [*@*] (Cannot resolve %s)\n", straddr);
  509.     return 0;
  510.     }
  511.     if ((remote = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  512.         printf("ERROR :Closing Link: [*@*] (Cannot create socket)\n");
  513.     return 0;
  514.     }
  515.     for (i = 0, p = (char *)&server; i < sizeof(server); i++, *p++ = 0);
  516.     server.sin_family = AF_INET;
  517.     server.sin_addr.s_addr = htonl(addr);
  518.     server.sin_port = htons(atoi(strport));
  519.     if (connect(remote, (struct sockaddr *)&server, sizeof(server)) < 0) {
  520.         printf("ERROR :Closing Link: [*@*] (Cannot connect to %s/%s)\n",
  521.            straddr, strport);
  522.     return 0;
  523.     }
  524. #endif
  525.  
  526.     return loop(remote);
  527. }
  528.  
  529.