home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / tcp / amitcp / amitcp-src-22.lha / AmiTCP-2.2 / src / util / letnet / letnet.c next >
Encoding:
C/C++ Source or Header  |  1993-11-01  |  6.6 KB  |  292 lines

  1. RCS_ID_C= "$Id: letnet.c,v 1.9 1993/11/01 08:10:43 ppessi Exp $";
  2. /*
  3.  * letnet.c --- a tcp filter for Amiga
  4.  *
  5.  * Author: Pekka Pessi <Pekka.Pessi@hut.fi>
  6.  *
  7.  * Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  8.  *                  Helsinki University of Technology, Finland.
  9.  *                  All rights reserved.
  10.  *
  11.  * Created      : Tue Mar 23 20:10:33 1993 ppessi
  12.  * Last modified: Mon Nov  1 10:10:32 1993 ppessi
  13.  *
  14.  * $Log: letnet.c,v $
  15.  * Revision 1.9  1993/11/01  08:10:43  ppessi
  16.  * Fixed bug with ObtainSocket()
  17.  *
  18.  */
  19.  
  20. static const char version[] = "$VER: letnet 2.0 (13.8.93)";
  21.  
  22. char copyright[] =
  23.      "Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
  24.                       "Helsinki University of Technology, Finland.\n"
  25.                       "All rights reserved.\n";
  26.  
  27. /****** netutil.doc/letnet **************************************************
  28. *
  29. *  NAME
  30. *       Letnet - a simple TCP connection tool
  31. *
  32. *  SYNOPSIS
  33. *       letnet HOSTNAME/A,PORT/A
  34. *
  35. *  DESCRIPTION
  36. *       Letnet connects to the specified TCP port at the specified host. The
  37. *       data read from standard input is sent to the host and data received
  38. *       from the connection is written to the standard output. Letnet
  39. *       terminates upon shutdown of the socket or receiving SIGBREAKF_CTRL_C
  40. *       signal.
  41. *
  42. *  ARGUMENTS
  43. *        HOSTNAME/A
  44. *               If there is no name service available, hostname may be given
  45. *               in the Internet dot notation.
  46. *
  47. *        PORT/A
  48. *               The port identifier is searched from the standard services
  49. *               (SEE ALSO netdb/services) database. A nonstandard
  50. *               service port may be specified in the numeric form, numbers
  51. *               between 1---65535 are acceptable. 
  52. *
  53. *  AUTHOR
  54. *       Pekka Pessi, the AmiTCP/IP Group, Helsinki University of Technology
  55. *
  56. *  SEE ALSO
  57. *       netdb/services, netdb/hosts       
  58. *
  59. *****************************************************************************
  60. *
  61. */
  62.  
  63. #ifdef AMIGA
  64. #if __SASC
  65. #include <proto/socket.h>
  66. #include <proto/dos.h>
  67. #include <clib/exec_protos.h>
  68. #include <pragmas/exec_sysbase_pragmas.h>
  69. #elif __GNUC__
  70. #include <inline/socket.h>
  71. #include <inline/exec.h>
  72. #else
  73. #include <clib/socket_protos.h>
  74. #endif
  75. #define ioctl IoctlSocket
  76. #endif /* AMIGA */
  77.  
  78. #include <errno.h>
  79. #include <netdb.h>
  80.  
  81. #include <sys/param.h>
  82. #include <sys/socket.h>
  83. #include <sys/ioctl.h>
  84. #include <netinet/in.h>
  85.  
  86. #include <signal.h>
  87.  
  88. #include <dos/dos.h>
  89. #include <dos/dostags.h>
  90. #include <exec/execbase.h>
  91.  
  92. #include <stdlib.h>
  93.  
  94. #include "letnet.h"
  95.  
  96. extern struct ExecBase *SysBase;
  97.  
  98. BPTR Stdin = NULL;
  99. BPTR Stdout = NULL;
  100. BPTR Stderr = NULL;
  101.  
  102. struct MsgPort *dadp = NULL; 
  103. struct SocketMessage *exitm = NULL; 
  104.  
  105. void
  106. _STIdosStdio(void)
  107. {
  108.   struct Process *p = (struct Process *)SysBase->ThisTask;
  109.  
  110.   Stdin = p->pr_CIS;
  111.   Stdout = p->pr_COS;
  112.   Stderr = p->pr_CES ? p->pr_CES : Stdout;
  113. }
  114.  
  115. void
  116. free_ports(void)
  117. {
  118.   if (exitm) DeleteIORequest(exitm);
  119.   exitm = NULL;
  120.  
  121.   if (dadp) DeleteMsgPort(dadp);
  122.   dadp = NULL;
  123. }
  124.  
  125. int
  126. wait_sender(void) {
  127.   do {
  128.     WaitPort(dadp);
  129.   } while (GetMsg(dadp) != exitm);
  130.   return exitm->sm_retval;
  131. }
  132.  
  133. void
  134. stop_sender(struct Process * sender_pid)
  135. {
  136.   Forbid();
  137.   /* Check that sender task is still around */
  138.   /* i.e. the exitm Message is not replied */
  139.   if (sender_pid && dadp->mp_MsgList.lh_Head != exitm)
  140.     Signal((struct Task *)sender_pid, SIGBREAKF_CTRL_C);
  141.   Permit();
  142. }
  143.  
  144. struct Process *
  145. start_sender(int s)
  146. {
  147.   struct Process *pid = NULL;
  148.  
  149.   dadp = CreateMsgPort();
  150.   exitm = CreateIORequest(dadp, sizeof(*exitm));
  151.  
  152.   if (!exitm || !dadp) {
  153.     FPrintf(Stderr, "letnet: memory or signals exhausted\n");
  154.     return NULL;
  155.   }
  156.  
  157.   if ((exitm->sm_id = ReleaseCopyOfSocket(s, -1L)) == -1) {
  158.     PrintNetFault(Errno(), "ReleaseCopyOfSocket");
  159.     return NULL;
  160.   }
  161.  
  162.   pid = CreateNewProcTags(NP_Entry, do_sender,
  163.               NP_Name, "sender",
  164.               NP_Output, Stderr,
  165.               NP_CloseOutput, FALSE,
  166.               NP_Input, Stdin,
  167.               NP_CloseInput, FALSE,
  168.               NP_ExitCode, exitcode,
  169.               NP_ExitData, exitm,
  170.               TAG_END, NULL);
  171.   if (pid == 0) {
  172.     /* We should not leave orphan sockets into the internal list */
  173.     (void)ObtainSocket((LONG)exitm->sm_id, PF_INET, SOCK_STREAM, NULL);
  174.   }
  175.  
  176.   return pid;
  177. }
  178.  
  179. int
  180. do_receiver(int s)
  181. {
  182.   int n, m, retval = 0;
  183.   char *recb = malloc(RECBUFLEN);
  184.  
  185.   if (!recb) {
  186.     PrintNetFault(Errno(), "buffer malloc");
  187.     retval = 0; goto Return;
  188.   }
  189.  
  190.   while (recv(s, recb, 1, 0) == 1) {
  191.     if (SetSignal(0L, 0L) & SIGBREAKF_CTRL_C) {
  192.       retval = 128; goto Return;
  193.     }
  194.     if (Write(Stdout, recb, 1) == -1) {
  195.       PrintFault(IoErr(), "Write");
  196.       retval = 20; goto Return;
  197.     }
  198.     if (ioctl(s, FIONREAD, (char *)&n)) {
  199.       PrintNetFault(Errno(), "FIONREAD");
  200.       retval = 1; goto Return;
  201.     }
  202.     while (n > 0) {
  203.       m = recv(s, recb, n > RECBUFLEN ? RECBUFLEN : n, 0);
  204.       if (m == -1) {
  205.     PrintNetFault(Errno(), "recv");
  206.     retval = 1; goto Return;
  207.       }
  208.       if (Write(Stdout, recb, m) != m) {
  209.     PrintFault(IoErr(), "Write");
  210.     retval = 1; goto Return;
  211.       }
  212.       n -= m;
  213.     }
  214.   }
  215.  
  216.  Return:
  217.   shutdown(s, 0);        /* no more receiving */
  218.   return retval;
  219. }
  220.  
  221. int
  222. main()
  223. {
  224.   struct sockaddr_in addr;
  225.   struct hostent *hp;
  226.   struct servent *sp;
  227.   long val;
  228.   unsigned long port;
  229.   int s;
  230.   struct Process *child; 
  231.   int retval = 0, retval2 = 0;
  232.   LONG args[3] = { 0, 0, 0};
  233.   struct RDArgs *rdargs = NULL;
  234.  
  235.   signal(SIGINT, SIG_IGN);
  236.  
  237.   atexit(free_ports);
  238.  
  239.   rdargs = ReadArgs("HOST/A,PORT/A", args, NULL);
  240.   if (!rdargs) {
  241.     PrintFault(IoErr(), "letnet");
  242.     exit(10);
  243.   }
  244.  
  245.   addr.sin_len = sizeof(addr);
  246.   addr.sin_family = AF_INET;
  247.   addr.sin_port = 0;
  248.   addr.sin_addr.s_addr = 0;
  249.  
  250.   if ((val = inet_addr((char *)args[0])) != -1)
  251.     addr.sin_addr.s_addr = val;
  252.   else if (hp = gethostbyname((char *)args[0]))
  253.     bcopy(hp->h_addr, (char *)&addr.sin_addr, hp->h_length);
  254.   else {
  255.     FPrintf(Stderr, "%s: unknown host\n", (char *)args[0]);
  256.     FreeArgs(rdargs);
  257.     exit(1);
  258.   }
  259.  
  260.   /* A port must be in the range 1 - 65535 */
  261.   if ((port = strtoul((char *)args[1], NULL, 0)) && port < 65536 )
  262.     addr.sin_port = port;
  263.   else if (sp = getservbyname((char *)args[1], "tcp"))
  264.     addr.sin_port = sp->s_port;
  265.   else {
  266.     FPrintf(Stderr, "%s: unknown port\n", (char *)args[1]);
  267.     FreeArgs(rdargs);
  268.     exit(1);
  269.   }
  270.  
  271.   FreeArgs(rdargs); rdargs = NULL;
  272.  
  273.   s = socket(PF_INET, SOCK_STREAM, NULL);
  274.  
  275.   if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  276.     PrintNetFault(Errno(), "connect");
  277.     exit(1);
  278.   }
  279.  
  280.   if (child = start_sender(s)) {
  281.     retval = do_receiver(s);
  282.     stop_sender(child);
  283.     retval2 = wait_sender();
  284.   } else {
  285.     FPrintf(Stderr, "letnet: couldn't start sender process\n");
  286.   }
  287.   if (!retval)
  288.     retval = retval2;
  289.  
  290.   exit(retval);
  291. }
  292.