home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C= "$Id: letnet.c,v 1.9 1993/11/01 08:10:43 ppessi Exp $";
- /*
- * letnet.c --- a tcp filter for Amiga
- *
- * Author: Pekka Pessi <Pekka.Pessi@hut.fi>
- *
- * Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
- * Helsinki University of Technology, Finland.
- * All rights reserved.
- *
- * Created : Tue Mar 23 20:10:33 1993 ppessi
- * Last modified: Mon Nov 1 10:10:32 1993 ppessi
- *
- * $Log: letnet.c,v $
- * Revision 1.9 1993/11/01 08:10:43 ppessi
- * Fixed bug with ObtainSocket()
- *
- */
-
- static const char version[] = "$VER: letnet 2.0 (13.8.93)";
-
- char copyright[] =
- "Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
- "Helsinki University of Technology, Finland.\n"
- "All rights reserved.\n";
-
- /****** netutil.doc/letnet **************************************************
- *
- * NAME
- * Letnet - a simple TCP connection tool
- *
- * SYNOPSIS
- * letnet HOSTNAME/A,PORT/A
- *
- * DESCRIPTION
- * Letnet connects to the specified TCP port at the specified host. The
- * data read from standard input is sent to the host and data received
- * from the connection is written to the standard output. Letnet
- * terminates upon shutdown of the socket or receiving SIGBREAKF_CTRL_C
- * signal.
- *
- * ARGUMENTS
- * HOSTNAME/A
- * If there is no name service available, hostname may be given
- * in the Internet dot notation.
- *
- * PORT/A
- * The port identifier is searched from the standard services
- * (SEE ALSO netdb/services) database. A nonstandard
- * service port may be specified in the numeric form, numbers
- * between 1---65535 are acceptable.
- *
- * AUTHOR
- * Pekka Pessi, the AmiTCP/IP Group, Helsinki University of Technology
- *
- * SEE ALSO
- * netdb/services, netdb/hosts
- *
- *****************************************************************************
- *
- */
-
- #ifdef AMIGA
- #if __SASC
- #include <proto/socket.h>
- #include <proto/dos.h>
- #include <clib/exec_protos.h>
- #include <pragmas/exec_sysbase_pragmas.h>
- #elif __GNUC__
- #include <inline/socket.h>
- #include <inline/exec.h>
- #else
- #include <clib/socket_protos.h>
- #endif
- #define ioctl IoctlSocket
- #endif /* AMIGA */
-
- #include <errno.h>
- #include <netdb.h>
-
- #include <sys/param.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <netinet/in.h>
-
- #include <signal.h>
-
- #include <dos/dos.h>
- #include <dos/dostags.h>
- #include <exec/execbase.h>
-
- #include <stdlib.h>
-
- #include "letnet.h"
-
- extern struct ExecBase *SysBase;
-
- BPTR Stdin = NULL;
- BPTR Stdout = NULL;
- BPTR Stderr = NULL;
-
- struct MsgPort *dadp = NULL;
- struct SocketMessage *exitm = NULL;
-
- void
- _STIdosStdio(void)
- {
- struct Process *p = (struct Process *)SysBase->ThisTask;
-
- Stdin = p->pr_CIS;
- Stdout = p->pr_COS;
- Stderr = p->pr_CES ? p->pr_CES : Stdout;
- }
-
- void
- free_ports(void)
- {
- if (exitm) DeleteIORequest(exitm);
- exitm = NULL;
-
- if (dadp) DeleteMsgPort(dadp);
- dadp = NULL;
- }
-
- int
- wait_sender(void) {
- do {
- WaitPort(dadp);
- } while (GetMsg(dadp) != exitm);
- return exitm->sm_retval;
- }
-
- void
- stop_sender(struct Process * sender_pid)
- {
- Forbid();
- /* Check that sender task is still around */
- /* i.e. the exitm Message is not replied */
- if (sender_pid && dadp->mp_MsgList.lh_Head != exitm)
- Signal((struct Task *)sender_pid, SIGBREAKF_CTRL_C);
- Permit();
- }
-
- struct Process *
- start_sender(int s)
- {
- struct Process *pid = NULL;
-
- dadp = CreateMsgPort();
- exitm = CreateIORequest(dadp, sizeof(*exitm));
-
- if (!exitm || !dadp) {
- FPrintf(Stderr, "letnet: memory or signals exhausted\n");
- return NULL;
- }
-
- if ((exitm->sm_id = ReleaseCopyOfSocket(s, -1L)) == -1) {
- PrintNetFault(Errno(), "ReleaseCopyOfSocket");
- return NULL;
- }
-
- pid = CreateNewProcTags(NP_Entry, do_sender,
- NP_Name, "sender",
- NP_Output, Stderr,
- NP_CloseOutput, FALSE,
- NP_Input, Stdin,
- NP_CloseInput, FALSE,
- NP_ExitCode, exitcode,
- NP_ExitData, exitm,
- TAG_END, NULL);
- if (pid == 0) {
- /* We should not leave orphan sockets into the internal list */
- (void)ObtainSocket((LONG)exitm->sm_id, PF_INET, SOCK_STREAM, NULL);
- }
-
- return pid;
- }
-
- int
- do_receiver(int s)
- {
- int n, m, retval = 0;
- char *recb = malloc(RECBUFLEN);
-
- if (!recb) {
- PrintNetFault(Errno(), "buffer malloc");
- retval = 0; goto Return;
- }
-
- while (recv(s, recb, 1, 0) == 1) {
- if (SetSignal(0L, 0L) & SIGBREAKF_CTRL_C) {
- retval = 128; goto Return;
- }
- if (Write(Stdout, recb, 1) == -1) {
- PrintFault(IoErr(), "Write");
- retval = 20; goto Return;
- }
- if (ioctl(s, FIONREAD, (char *)&n)) {
- PrintNetFault(Errno(), "FIONREAD");
- retval = 1; goto Return;
- }
- while (n > 0) {
- m = recv(s, recb, n > RECBUFLEN ? RECBUFLEN : n, 0);
- if (m == -1) {
- PrintNetFault(Errno(), "recv");
- retval = 1; goto Return;
- }
- if (Write(Stdout, recb, m) != m) {
- PrintFault(IoErr(), "Write");
- retval = 1; goto Return;
- }
- n -= m;
- }
- }
-
- Return:
- shutdown(s, 0); /* no more receiving */
- return retval;
- }
-
- int
- main()
- {
- struct sockaddr_in addr;
- struct hostent *hp;
- struct servent *sp;
- long val;
- unsigned long port;
- int s;
- struct Process *child;
- int retval = 0, retval2 = 0;
- LONG args[3] = { 0, 0, 0};
- struct RDArgs *rdargs = NULL;
-
- signal(SIGINT, SIG_IGN);
-
- atexit(free_ports);
-
- rdargs = ReadArgs("HOST/A,PORT/A", args, NULL);
- if (!rdargs) {
- PrintFault(IoErr(), "letnet");
- exit(10);
- }
-
- addr.sin_len = sizeof(addr);
- addr.sin_family = AF_INET;
- addr.sin_port = 0;
- addr.sin_addr.s_addr = 0;
-
- if ((val = inet_addr((char *)args[0])) != -1)
- addr.sin_addr.s_addr = val;
- else if (hp = gethostbyname((char *)args[0]))
- bcopy(hp->h_addr, (char *)&addr.sin_addr, hp->h_length);
- else {
- FPrintf(Stderr, "%s: unknown host\n", (char *)args[0]);
- FreeArgs(rdargs);
- exit(1);
- }
-
- /* A port must be in the range 1 - 65535 */
- if ((port = strtoul((char *)args[1], NULL, 0)) && port < 65536 )
- addr.sin_port = port;
- else if (sp = getservbyname((char *)args[1], "tcp"))
- addr.sin_port = sp->s_port;
- else {
- FPrintf(Stderr, "%s: unknown port\n", (char *)args[1]);
- FreeArgs(rdargs);
- exit(1);
- }
-
- FreeArgs(rdargs); rdargs = NULL;
-
- s = socket(PF_INET, SOCK_STREAM, NULL);
-
- if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
- PrintNetFault(Errno(), "connect");
- exit(1);
- }
-
- if (child = start_sender(s)) {
- retval = do_receiver(s);
- stop_sender(child);
- retval2 = wait_sender();
- } else {
- FPrintf(Stderr, "letnet: couldn't start sender process\n");
- }
- if (!retval)
- retval = retval2;
-
- exit(retval);
- }
-