home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / useful / comm / tcp / amitcp / src / util / letnet / letnet.c next >
Encoding:
C/C++ Source or Header  |  1994-05-03  |  6.9 KB  |  301 lines

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