Code to handle TCP connections.
Copyright (C) 1991, 1992 Ian Lance Taylor
This file is part of the Taylor UUCP package.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
c/o AIRS, P.O. Box 520, Waltham, MA 02254.
Revision 1.16 1992/03/30 15:37:22 ian
Petri Helenius: TCP server never started uuxqt
Revision 1.15 1992/03/17 02:44:08 ian
Revision 1.14 1992/03/17 00:34:10 ian
Revision 1.13 1992/03/15 04:51:17 ian
Keep an array of signals we've received rather than a single variable
Revision 1.12 1992/03/15 01:54:46 ian
All execs are now done in isspawn, all waits are done in iswait
Revision 1.11 1992/03/12 19:56:10 ian
Debugging based on types rather than number
Revision 1.10 1992/03/11 02:09:57 ian
Franc,ois Pinard: retry fork several times before giving up
Revision 1.9 1992/03/10 22:57:03 ian
Petri Helenius: have server fork twice to avoid zombies
Revision 1.8 1992/02/08 03:54:18 ian
Include <string.h> only in <uucp.h>, added 1992 copyright
Revision 1.7 1991/12/28 03:49:23 ian
Added HAVE_MEMFNS and HAVE_BFNS; changed uses of memset to bzero
Revision 1.6 1991/12/26 22:54:32 ian
Monty Solomon: cast arguments to avoid prototype errors
Revision 1.5 1991/12/22 22:14:19 ian
Monty Solomon: added HAVE_UNISTD_H configuration parameter
Revision 1.4 1991/12/10 19:45:05 ian
Added ulog_device to record device name for log file
Revision 1.3 1991/11/24 20:06:08 ian
Michael Haberler: itcp_port_number of a number wasn't calling htons
Revision 1.2 1991/11/14 03:20:13 ian
Added seven-bit and reliable commands to help when selecting protocols
Revision 1.1 1991/11/13 20:38:00 ian
char tcp_rcsid
[] = "$Id: tcp.c,v 1.16 1992/03/30 15:37:22 ian Rel $";
#if USE_STDIO && HAVE_UNISTD_H
/* External functions. */
extern int socket (), bind (), listen (), accept (), connect ();
/* This code handles TCP connections by providing a set of routines
that are called by the port routines. It assumes a Berkeley socket
/* The normal "uucp" port number. */
/* Local function to get the port number from a name. */
static int itcp_port_number
P((const char *zport
));
/* Lock a port. There is no need to lock a TCP port. */
/* Open a port. If the fwait argument is TRUE, we are running as a
server. Otherwise we are just trying to reach another system. */
ftcp_open (qport
, ibaud
, fwait
)
qport
->u
.stcp
.o
= socket (AF_INET
, SOCK_STREAM
, 0);
if (qport
->u
.stcp
.o
== -1)
ulog (LOG_ERROR
, "socket: %s", strerror (errno
));
/* If we aren't waiting for a connection, we're done. */
/* Run as a server and wait for a new connection. The code in
uucico.c has already detached us from our controlling terminal.
From this point on if the server gets an error we exit; we only
return if we have received a connection. It would be more robust
to respawn the server if it fails; someday. */
bzero ((pointer
) &s
, sizeof s
);
s
.sin_port
= itcp_port_number (qport
->u
.stcp
.zport
);
s
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
if (bind (qport
->u
.stcp
.o
, (struct sockaddr
*) &s
, sizeof s
) == -1)
ulog (LOG_ERROR
, "bind: %s", strerror (errno
));
if (listen (qport
->u
.stcp
.o
, 5) == -1)
ulog (LOG_ERROR
, "listen: %s", strerror (errno
));
DEBUG_MESSAGE0 (DEBUG_PORT
,
"ftcp_open: Waiting for connections");
onew
= accept (qport
->u
.stcp
.o
, (struct sockaddr
*) &s
, &clen
);
ulog (LOG_ERROR
, "accept: %s", strerror (errno
));
DEBUG_MESSAGE0 (DEBUG_PORT
,
"ftcp_open: Got connection; forking");
ulog (LOG_ERROR
, "fork: %s", strerror (errno
));
(void) close (qport
->u
.stcp
.o
);
/* Now we fork and let our parent die, so that we become
a child of init. This lets the main server code wait
for its child and then continue without accumulating
ulog (LOG_ERROR
, "fork: %s", strerror (errno
));
/* Now wait for the child. */
(void) iswait ((unsigned long) ipid
, (const char *) NULL
);
/* Avoid compiler warnings. */
ftcp_close (qport
, fsuccess
)
if (close (qport
->u
.stcp
.o
) == -1)
ulog (LOG_ERROR
, "close: %s", strerror (errno
));
/* Reset the port. This will be called by a child which was forked
off in ftcp_open, above. We don't want uucico to continue looping
and giving login prompts, so we pretend that we received a SIGINT
signal. This should probably be handled more cleanly. */
afSignal
[INDEXSIG_SIGINT
] = TRUE
;
/* Dial out on a TCP port, so to speak: connect to a remote computer. */
ftcp_dial (qport
, qsys
, pcproto_params
, pqproto_params
, pireliable
)
const struct ssysteminfo
*qsys
;
struct sproto_param
**pqproto_params
;
/* There are no dialer protocol parameters, but a TCP connection is
*pireliable
= (RELIABLE_SPECIFIED
| RELIABLE_ENDTOEND
| RELIABLE_RELIABLE
| RELIABLE_EIGHT
);
/* Cast argument to avoid prototype error on NeXT. */
q
= gethostbyname ((char *) zhost
);
ulog (LOG_ERROR
, "gethostbyname (%s): %s", zhost
, strerror (errno
));
s
.sin_family
= q
->h_addrtype
;
s
.sin_port
= itcp_port_number (qport
->u
.stcp
.zport
);
memcpy (&s
.sin_addr
.s_addr
, q
->h_addr
, q
->h_length
);
if (connect (qport
->u
.stcp
.o
, (struct sockaddr
*) &s
, sizeof s
) == -1)
ulog (LOG_ERROR
, "connect: %s", strerror (errno
));
/* Return the baud rate. */
/* Get the port number given a name. The argument will almost always
be "uucp" so we cache that value. The return value is always in
network byte order. This returns -1 on error. */
fuucp
= strcmp (zname
, "uucp") == 0;
/* Try it as a number first. */
i
= strtol (zname
, &zend
, 10);
if (i
!= 0 && *zend
== '\0')
/* Cast arguments to avoid prototype errors on NeXT. */
q
= getservbyname ((char *) zname
, (char *) "tcp");
/* We know that the "uucp" service should be 540, even if isn't
iuucp
= htons (IUUCP_PORT
);
ulog (LOG_ERROR
, "getservbyname (%s): %s", zname
, strerror (errno
));