aboutsummaryrefslogtreecommitdiffstats
path: root/gnu/libexec/uucp/uucico
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/libexec/uucp/uucico')
-rw-r--r--gnu/libexec/uucp/uucico/Makefile6
-rw-r--r--gnu/libexec/uucp/uucico/prote.c4
-rw-r--r--gnu/libexec/uucp/uucico/protf.c14
-rw-r--r--gnu/libexec/uucp/uucico/protg.c83
-rw-r--r--gnu/libexec/uucp/uucico/proti.c261
-rw-r--r--gnu/libexec/uucp/uucico/protj.c7
-rw-r--r--gnu/libexec/uucp/uucico/prott.c7
-rw-r--r--gnu/libexec/uucp/uucico/protz.c4
-rw-r--r--gnu/libexec/uucp/uucico/rec.c238
-rw-r--r--gnu/libexec/uucp/uucico/send.c271
-rw-r--r--gnu/libexec/uucp/uucico/time.c10
-rw-r--r--gnu/libexec/uucp/uucico/trans.c118
-rw-r--r--gnu/libexec/uucp/uucico/uucico.8176
-rw-r--r--gnu/libexec/uucp/uucico/uucico.c762
-rw-r--r--gnu/libexec/uucp/uucico/xcmd.c31
15 files changed, 1439 insertions, 553 deletions
diff --git a/gnu/libexec/uucp/uucico/Makefile b/gnu/libexec/uucp/uucico/Makefile
index 6cd270934bbf..f6ba17130d0c 100644
--- a/gnu/libexec/uucp/uucico/Makefile
+++ b/gnu/libexec/uucp/uucico/Makefile
@@ -1,9 +1,9 @@
# Makefile for uucico
-# $Id: Makefile,v 1.2 1993/08/06 23:38:23 rgrimes Exp $
+# $Id: Makefile,v 1.6 1994/05/31 15:55:43 ache Exp $
BINDIR= $(sbindir)
BINOWN= $(owner)
-BINMODE= 4555
+BINMODE= 4555
PROG= uucico
SRCS= uucico.c trans.c send.c rec.c xcmd.c prot.c protg.c protf.c \
@@ -12,7 +12,7 @@ SRCS= uucico.c trans.c send.c rec.c xcmd.c prot.c protg.c protf.c \
LDADD+= $(LIBUNIX) $(LIBUUCONF) $(LIBUUCP)
DPADD+= $(LIBUNIX) $(LIBUUCONF) $(LIBUUCP)
CFLAGS+= -I$(.CURDIR)/../common_sources\
- -DVERSION=\"$(VERSION)\"
+ -DVERSION=\"$(VERSION)\" -DOWNER=\"$(owner)\"
MAN8= uucico.8
diff --git a/gnu/libexec/uucp/uucico/prote.c b/gnu/libexec/uucp/uucico/prote.c
index 9b824651c2f7..c5cb0cf649ad 100644
--- a/gnu/libexec/uucp/uucico/prote.c
+++ b/gnu/libexec/uucp/uucico/prote.c
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char prote_rcsid[] = "$Id: prote.c,v 1.1 1993/08/05 18:27:09 conklin Exp $";
+const char prote_rcsid[] = "$Id: prote.c,v 1.2 1994/05/07 18:13:43 ache Exp $";
#endif
#include "uudefs.h"
diff --git a/gnu/libexec/uucp/uucico/protf.c b/gnu/libexec/uucp/uucico/protf.c
index 96b213157cee..8ba786ea127c 100644
--- a/gnu/libexec/uucp/uucico/protf.c
+++ b/gnu/libexec/uucp/uucico/protf.c
@@ -1,7 +1,7 @@
/* protf.c
The 'f' protocol.
- Copyright (C) 1991, 1992 Ian Lance Taylor
+ Copyright (C) 1991, 1992, 1993 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char protf_rcsid[] = "$Id: protf.c,v 1.1 1993/08/05 18:27:10 conklin Exp $";
+const char protf_rcsid[] = "$Id: protf.c,v 1.2 1994/05/07 18:13:45 ache Exp $";
#endif
#include <ctype.h>
@@ -340,6 +340,10 @@ ffprocess_data (qdaemon, pfexit, pcneed)
{
for (i = iPrecstart; i < CRECBUFLEN && i != iPrecend; i++)
{
+ /* Some systems seem to send characters with parity, so
+ strip the parity bit. */
+ abPrecbuf[i] &= 0x7f;
+
if (abPrecbuf[i] == '\r')
{
int istart;
@@ -395,7 +399,9 @@ ffprocess_data (qdaemon, pfexit, pcneed)
{
int b;
- b = *zfrom++ & 0xff;
+ /* Some systems seem to send characters with parity, so
+ strip the parity bit. */
+ b = *zfrom++ & 0x7f;
if (b < 040 || b > 0176)
{
ulog (LOG_ERROR, "Illegal byte %d", b);
diff --git a/gnu/libexec/uucp/uucico/protg.c b/gnu/libexec/uucp/uucico/protg.c
index 39a79212cf77..0b58197a1da1 100644
--- a/gnu/libexec/uucp/uucico/protg.c
+++ b/gnu/libexec/uucp/uucico/protg.c
@@ -1,7 +1,7 @@
/* protg.c
The 'g' protocol.
- Copyright (C) 1991, 1992 Ian Lance Taylor
+ Copyright (C) 1991, 1992, 1993, 1994 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char protg_rcsid[] = "$Id: protg.c,v 1.1 1993/08/05 18:27:11 conklin Exp $";
+const char protg_rcsid[] = "$Id: protg.c,v 1.2 1994/05/07 18:13:46 ache Exp $";
#endif
#include <ctype.h>
@@ -346,6 +346,12 @@ static long cGbad_order;
received). */
static long cGremote_rejects;
+/* Number of duplicate RR packets treated as RJ packets. Some UUCP
+ packages appear to never send RJ packets, but only RR packets. If
+ no RJ has been seen, fgprocess_data treats a duplicate RR as an RJ
+ and increments this variable. */
+static long cGremote_duprrs;
+
/* The error level. This is the total number of errors as adjusted by
cGerror_decay. */
static long cGerror_level;
@@ -419,6 +425,7 @@ fgstart (qdaemon, pzlog)
cGbad_checksum = 0;
cGbad_order = 0;
cGremote_rejects = 0;
+ cGremote_duprrs = 0;
cGerror_level = 0;
cGexpect_bad_order = 0;
@@ -440,6 +447,13 @@ fgstart (qdaemon, pzlog)
iseg = 1;
}
+ if (iGrequest_winsize <= 0 || iGrequest_winsize > 7)
+ {
+ ulog (LOG_ERROR, "Illegal window size %d for '%c' protocol",
+ iGrequest_winsize, qdaemon->qproto->bname);
+ iGrequest_winsize = IWINDOW;
+ }
+
fgota = FALSE;
fgotb = FALSE;
for (i = 0; i < cGstartup_retries; i++)
@@ -503,10 +517,14 @@ fgstart (qdaemon, pzlog)
if (! fginit_sendbuffers (TRUE))
return FALSE;
- *pzlog = zbufalc (sizeof "protocol '' packet size window " + 50);
- sprintf (*pzlog, "protocol '%c' packet size %d window %d",
+ *pzlog =
+ zbufalc (sizeof "protocol '' sending packet/window / receiving /"
+ + 64);
+ sprintf (*pzlog,
+ "protocol '%c' sending packet/window %d/%d receiving %d/%d",
qdaemon->qproto->bname, (int) iGremote_packsize,
- (int) iGremote_winsize);
+ (int) iGremote_winsize, (int) iGrequest_packsize,
+ (int) iGrequest_winsize);
return TRUE;
}
@@ -528,6 +546,22 @@ fbiggstart (qdaemon, pzlog)
fGshort_packets = FALSE;
return fgstart (qdaemon, pzlog);
}
+
+/* The 'v' protocol is identical to the 'g' protocol, except that the
+ packet size defaults to 512 bytes. Rather than really get it
+ right, we automatically switch from the usual default of 64 to 512.
+ This won't work correctly if somebody does protocol-parameter v
+ packet-size 64. */
+
+boolean
+fvstart (qdaemon, pzlog)
+ struct sdaemon *qdaemon;
+ char **pzlog;
+{
+ if (iGrequest_packsize == IPACKSIZE)
+ iGrequest_packsize = 1024;
+ return fgstart (qdaemon, pzlog);
+}
/* Exchange initialization messages with the other system.
@@ -671,10 +705,12 @@ fgshutdown (qdaemon)
if (cGbad_hdr != 0
|| cGbad_checksum != 0
|| cGbad_order != 0
- || cGremote_rejects != 0)
+ || cGremote_rejects != 0
+ || cGremote_duprrs != 0)
ulog (LOG_NORMAL,
"Errors: header %ld, checksum %ld, order %ld, remote rejects %ld",
- cGbad_hdr, cGbad_checksum, cGbad_order, cGremote_rejects);
+ cGbad_hdr, cGbad_checksum, cGbad_order,
+ cGremote_duprrs + cGremote_rejects);
/* Reset all the parameters to their default values, so that the
protocol parameters used for this connection do not affect the
@@ -739,7 +775,8 @@ fgsendcmd (qdaemon, z, ilocal, iremote)
}
memcpy (zpacket, z, clen);
- bzero (zpacket + clen, csize - clen);
+ if (csize > clen)
+ bzero (zpacket + clen, csize - clen);
fagain = FALSE;
if (! fgsenddata (qdaemon, zpacket, csize, 0, 0, (long) 0))
@@ -894,7 +931,8 @@ fgsenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
--zdata;
zdata[0] = (char) cshort;
zdata[-1] = '\0';
- bzero (zdata + cdata + 1, cshort - 1);
+ if (cshort > 1)
+ bzero (zdata + cdata + 1, cshort - 1);
}
else
{
@@ -1568,12 +1606,15 @@ fgprocess_data (qdaemon, fdoacks, freturncontrol, pfexit, pcneed, pffound)
/* Annoyingly, some UUCP packages appear to send an RR packet
rather than an RJ packet when they want a packet to be
- resent. If we get a duplicate RR, we treat it as an RJ. */
+ resent. If we get a duplicate RR and we've never seen an RJ,
+ we treat the RR as an RJ. */
fduprr = FALSE;
- if (CONTROL_TT (ab[IFRAME_CONTROL]) == CONTROL
+ if (cGremote_rejects == 0
+ && CONTROL_TT (ab[IFRAME_CONTROL]) == CONTROL
&& CONTROL_XXX (ab[IFRAME_CONTROL]) == RR
&& iGremote_ack == CONTROL_YYY (ab[IFRAME_CONTROL])
- && INEXTSEQ (iGremote_ack) != iGsendseq)
+ && INEXTSEQ (iGremote_ack) != iGsendseq
+ && iGretransmit_seq != -1)
{
DEBUG_MESSAGE0 (DEBUG_PROTO | DEBUG_ABNORMAL,
"fgprocess_data: Treating duplicate RR as RJ");
@@ -1581,11 +1622,12 @@ fgprocess_data (qdaemon, fdoacks, freturncontrol, pfexit, pcneed, pffound)
}
/* Update the received sequence number from the yyy field of a
- data packet or an RR control packet. If we've been delaying
- sending packets until we received an ack, this may send out
- some packets. */
- if (CONTROL_TT (ab[IFRAME_CONTROL]) != CONTROL
- || CONTROL_XXX (ab[IFRAME_CONTROL]) == RR)
+ data packet (if it is the one we are expecting) or an RR
+ control packet. If we've been delaying sending packets until
+ we received an ack, this may send out some packets. */
+ if ((CONTROL_TT (ab[IFRAME_CONTROL]) != CONTROL
+ && CONTROL_XXX (ab[IFRAME_CONTROL]) == INEXTSEQ (iGrecseq))
+ || (CONTROL_XXX (ab[IFRAME_CONTROL]) == RR && ! fduprr))
{
if (! fggot_ack (qdaemon, CONTROL_YYY (ab[IFRAME_CONTROL])))
return FALSE;
@@ -1773,7 +1815,10 @@ fgprocess_data (qdaemon, fdoacks, freturncontrol, pfexit, pcneed, pffound)
iGsendseq, iGretransmit_seq);
++cGresent_packets;
- ++cGremote_rejects;
+ if (fduprr)
+ ++cGremote_duprrs;
+ else
+ ++cGremote_rejects;
++cGerror_level;
if (! fgcheck_errors (qdaemon))
return FALSE;
diff --git a/gnu/libexec/uucp/uucico/proti.c b/gnu/libexec/uucp/uucico/proti.c
index d14d42b42db0..fd243de23731 100644
--- a/gnu/libexec/uucp/uucico/proti.c
+++ b/gnu/libexec/uucp/uucico/proti.c
@@ -1,7 +1,7 @@
/* proti.c
The 'i' protocol.
- Copyright (C) 1992 Ian Lance Taylor
+ Copyright (C) 1992, 1993 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char proti_rcsid[] = "$Id: proti.c,v 1.1 1993/08/05 18:27:12 conklin Exp $";
+const char proti_rcsid[] = "$Id: proti.c,v 1.2 1994/05/07 18:13:48 ache Exp $";
#endif
#include <ctype.h>
@@ -153,7 +153,10 @@ const char proti_rcsid[] = "$Id: proti.c,v 1.1 1993/08/05 18:27:12 conklin Exp $
#define IMAXSEQ 32
/* Get the next sequence number given a sequence number. */
-#define INEXTSEQ(i) ((i + 1) & (IMAXSEQ - 1))
+#define INEXTSEQ(i) (((i) + 1) & (IMAXSEQ - 1))
+
+/* Get the previous sequence number given a sequence number. */
+#define IPREVSEQ(i) (((i) + IMAXSEQ - 1) & (IMAXSEQ - 1))
/* Compute i1 - i2 in sequence space (i.e., the number of packets from
i2 to i1). */
@@ -216,17 +219,14 @@ static int iIremote_packsize;
static int iIalc_packsize;
/* Forced remote packet size, used if non-zero (protocol parameter
- ``remote-packet-size''). */
+ ``remote-packet-size''). There is no forced remote window size
+ because the ACK strategy requires that both sides agree on the
+ window size. */
static int iIforced_remote_packsize = 0;
-/* Remote window size (set from SYNC packet or from
- iIforced_remote_winsize). */
+/* Remote window size (set from SYNC packet). */
static int iIremote_winsize;
-/* Forced remote window size, used if non-zero (protocol parameter
- ``remote-window''). */
-static int iIforced_remote_winsize = 0;
-
/* Timeout to use when sending the SYNC packet (protocol
parameter ``sync-timeout''). */
int cIsync_timeout = CSYNC_TIMEOUT;
@@ -251,6 +251,11 @@ static int cIerrors = CERRORS;
the error level by one (protocol parameter ``error-decay''). */
static int cIerror_decay = CERROR_DECAY;
+/* The number of packets we should wait to receive before sending an
+ ACK; this is set by default to half the window size we have
+ requested (protocol parameter ``ack-frequency''). */
+static int cIack_frequency = 0;
+
/* The set of characters to avoid (protocol parameter ``avoid'').
This is actually part of the 'j' protocol; it is defined in this
file because the 'i' and 'j' protocols use the same protocol
@@ -334,8 +339,6 @@ struct uuconf_cmdtab asIproto_params[] =
{ "window", UUCONF_CMDTABTYPE_INT, (pointer) &iIrequest_winsize, NULL },
{ "remote-packet-size", UUCONF_CMDTABTYPE_INT,
(pointer) &iIforced_remote_packsize, NULL },
- { "remote-window", UUCONF_CMDTABTYPE_INT,
- (pointer) &iIforced_remote_winsize, NULL },
{ "sync-timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cIsync_timeout,
NULL },
{ "sync-retries", UUCONF_CMDTABTYPE_INT, (pointer) &cIsync_retries,
@@ -344,6 +347,7 @@ struct uuconf_cmdtab asIproto_params[] =
{ "retries", UUCONF_CMDTABTYPE_INT, (pointer) &cIretries, NULL },
{ "errors", UUCONF_CMDTABTYPE_INT, (pointer) &cIerrors, NULL },
{ "error-decay", UUCONF_CMDTABTYPE_INT, (pointer) &cIerror_decay, NULL },
+ { "ack-frequency", UUCONF_CMDTABTYPE_INT, (pointer) &cIack_frequency, NULL },
/* The ``avoid'' protocol parameter is part of the 'j' protocol, but
it is convenient for the 'i' and 'j' protocols to share the same
protocol parameter table. */
@@ -398,7 +402,7 @@ fijstart (qdaemon, pzlog, imaxpacksize, pfsend, pfreceive)
boolean (*pfreceive) P((struct sconnection *qconn, size_t cneed,
size_t *pcrec, int ctimeout, boolean freport));
{
- char ab[CHDRLEN + 3 + CCKSUMLEN];
+ char ab[CHDRLEN + 4 + CCKSUMLEN];
unsigned long icksum;
int ctries;
int csyncs;
@@ -414,10 +418,6 @@ fijstart (qdaemon, pzlog, imaxpacksize, pfsend, pfreceive)
else
iIremote_packsize = iIforced_remote_packsize;
iIalc_packsize = 0;
- if (iIforced_remote_winsize <= 0 || iIforced_remote_winsize >= IMAXSEQ)
- iIforced_remote_winsize = 0;
- else
- iIremote_winsize = iIforced_remote_winsize;
iIsendseq = 1;
iIrecseq = 0;
@@ -435,16 +435,41 @@ fijstart (qdaemon, pzlog, imaxpacksize, pfsend, pfreceive)
cIbad_cksum = 0;
cIremote_rejects = 0;
+ if (iIrequest_packsize < 0 || iIrequest_packsize > imaxpacksize)
+ {
+ ulog (LOG_ERROR, "Illegal protocol '%c' packet size; using %d",
+ qdaemon->qproto->bname, imaxpacksize);
+ iIrequest_packsize = imaxpacksize;
+ }
+
+ /* The maximum permissible window size is 16. Otherwise the
+ protocol can get confused because a duplicated packet may arrive
+ out of order. If the window size is large in such a case, the
+ duplicate packet may be treated as a packet in the upcoming
+ window, causing the protocol to assume that all intermediate
+ packets have been lost, leading to immense confusion. */
+ if (iIrequest_winsize < 0 || iIrequest_winsize > IMAXSEQ / 2)
+ {
+ ulog (LOG_ERROR, "Illegal protocol '%c' window size; using %d",
+ qdaemon->qproto->bname, IREQUEST_WINSIZE);
+ iIrequest_winsize = IREQUEST_WINSIZE;
+ }
+
+ /* The default for the ACK frequency is half the window size. */
+ if (cIack_frequency <= 0 || cIack_frequency >= iIrequest_winsize)
+ cIack_frequency = iIrequest_winsize / 2;
+
ab[IHDR_INTRO] = IINTRO;
ab[IHDR_LOCAL] = ab[IHDR_REMOTE] = IHDRWIN_SET (0, 0);
- ab[IHDR_CONTENTS1] = IHDRCON_SET1 (SYNC, qdaemon->fcaller, 3);
- ab[IHDR_CONTENTS2] = IHDRCON_SET2 (SYNC, qdaemon->fcaller, 3);
+ ab[IHDR_CONTENTS1] = IHDRCON_SET1 (SYNC, qdaemon->fcaller, 4);
+ ab[IHDR_CONTENTS2] = IHDRCON_SET2 (SYNC, qdaemon->fcaller, 4);
ab[IHDR_CHECK] = IHDRCHECK_VAL (ab);
ab[CHDRLEN + 0] = (iIrequest_packsize >> 8) & 0xff;
ab[CHDRLEN + 1] = iIrequest_packsize & 0xff;
ab[CHDRLEN + 2] = iIrequest_winsize;
- icksum = icrc (ab + CHDRLEN, 3, ICRCINIT);
- UCKSUM_SET (ab + CHDRLEN + 3, icksum);
+ ab[CHDRLEN + 3] = qdaemon->cchans;
+ icksum = icrc (ab + CHDRLEN, 4, ICRCINIT);
+ UCKSUM_SET (ab + CHDRLEN + 4, icksum);
/* The static cIsyncs is incremented each time a SYNC packet is
received. */
@@ -455,11 +480,11 @@ fijstart (qdaemon, pzlog, imaxpacksize, pfsend, pfreceive)
{
boolean ftimedout;
- DEBUG_MESSAGE2 (DEBUG_PROTO,
- "fistart: Sending SYNC packsize %d winsize %d",
- iIrequest_packsize, iIrequest_winsize);
+ DEBUG_MESSAGE3 (DEBUG_PROTO,
+ "fistart: Sending SYNC packsize %d winsize %d channels %d",
+ iIrequest_packsize, iIrequest_winsize, qdaemon->cchans);
- if (! (*pfIsend) (qdaemon->qconn, ab, CHDRLEN + 3 + CCKSUMLEN,
+ if (! (*pfIsend) (qdaemon->qconn, ab, CHDRLEN + 4 + CCKSUMLEN,
TRUE))
return FALSE;
@@ -509,11 +534,15 @@ fijstart (qdaemon, pzlog, imaxpacksize, pfsend, pfreceive)
if (iseq >= IMAXSEQ)
{
- *pzlog = zbufalc (sizeof "protocol 'i' packet size %d window %d"
- + 50);
- sprintf (*pzlog, "protocol '%c' packet size %d window %d",
- qdaemon->qproto->bname, iIremote_packsize,
- iIremote_winsize);
+ *pzlog =
+ zbufalc (sizeof "protocol '' sending packet/window / receiving /"
+ + 64);
+ sprintf (*pzlog,
+ "protocol '%c' sending packet/window %d/%d receiving %d/%d",
+ qdaemon->qproto->bname, (int) iIremote_packsize,
+ (int) iIremote_winsize, (int) iIrequest_packsize,
+ (int) iIrequest_winsize);
+
iIalc_packsize = iIremote_packsize;
return TRUE;
@@ -575,13 +604,13 @@ fishutdown (qdaemon)
iIrequest_packsize = IREQUEST_PACKSIZE;
iIrequest_winsize = IREQUEST_WINSIZE;
iIforced_remote_packsize = 0;
- iIforced_remote_winsize = 0;
cIsync_timeout = CSYNC_TIMEOUT;
cIsync_retries = CSYNC_RETRIES;
cItimeout = CTIMEOUT;
cIretries = CRETRIES;
cIerrors = CERRORS;
cIerror_decay = CERROR_DECAY;
+ cIack_frequency = 0;
zJavoid_parameter = ZAVOID;
return TRUE;
@@ -835,8 +864,9 @@ fisenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
iIlocal_ack = iIrecseq;
zhdr[IHDR_CHECK] = IHDRCHECK_VAL (zhdr);
- DEBUG_MESSAGE2 (DEBUG_PROTO, "fisenddata: Sending packet %d (%d bytes)",
- iIsendseq, (int) cdata);
+ DEBUG_MESSAGE4 (DEBUG_PROTO,
+ "fisenddata: Sending packet %d size %d local %d remote %d",
+ iIsendseq, (int) cdata, ilocal, iremote);
iIsendseq = INEXTSEQ (iIsendseq);
++cIsent_packets;
@@ -977,6 +1007,8 @@ ficheck_errors (qdaemon)
char absync[CHDRLEN + 3 + CCKSUMLEN];
unsigned long icksum;
+ /* Don't bother sending the number of channels in this
+ packet. */
iIrequest_packsize /= 2;
absync[IHDR_INTRO] = IINTRO;
absync[IHDR_LOCAL] = IHDRWIN_SET (0, 0);
@@ -1127,9 +1159,9 @@ fiprocess_data (qdaemon, pfexit, pffound, pcneed)
if (iIrequest_winsize > 0
&& CSEQDIFF (iseq, iIlocal_ack) > iIrequest_winsize)
{
- DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
- "fiprocess_data: Out of order packet %d",
- iseq);
+ DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fiprocess_data: Out of order packet %d (ack %d)",
+ iseq, iIlocal_ack);
++cIbad_order;
if (! ficheck_errors (qdaemon))
@@ -1253,7 +1285,27 @@ fiprocess_data (qdaemon, pfexit, pffound, pcneed)
if (iseq != -1)
{
- afInaked[iseq] = FALSE;
+ /* If we already sent a NAK for this packet, and we have not
+ seen the previous packet, then forget that we sent a NAK
+ for this and any preceding packets. This is to handle
+ the following sequence:
+ receive packet 0
+ packets 1 and 2 lost
+ receive packet 3
+ send NAK 1
+ send NAK 2
+ packet 1 lost
+ receive packet 2
+ At this point we want to send NAK 1. */
+ if (afInaked[iseq]
+ && azIrecbuffers[IPREVSEQ (iseq)] == NULL)
+ {
+ for (i = INEXTSEQ (iIrecseq);
+ i != iseq;
+ i = INEXTSEQ (i))
+ afInaked[i] = FALSE;
+ afInaked[iseq] = FALSE;
+ }
/* If we haven't handled all previous packets, we must save
off this packet and deal with it later. */
@@ -1263,16 +1315,16 @@ fiprocess_data (qdaemon, pfexit, pffound, pcneed)
|| (iIrequest_winsize > 0
&& CSEQDIFF (iseq, iIrecseq) > iIrequest_winsize))
{
- DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
- "fiprocess_data: Ignoring out of order packet %d",
- iseq);
+ DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fiprocess_data: Ignoring out of order packet %d (recseq %d)",
+ iseq, iIrecseq);
continue;
}
else
{
- DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
- "fiprocess_data: Saving unexpected packet %d",
- iseq);
+ DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fiprocess_data: Saving unexpected packet %d (recseq %d)",
+ iseq, iIrecseq);
if (azIrecbuffers[iseq] == NULL)
{
@@ -1352,7 +1404,7 @@ fiprocess_data (qdaemon, pfexit, pffound, pcneed)
However, it can happen if we receive a burst of short
packets, such as a set of command acknowledgements. */
if (iIrequest_winsize > 0
- && CSEQDIFF (iIrecseq, iIlocal_ack) >= iIrequest_winsize / 2)
+ && CSEQDIFF (iIrecseq, iIlocal_ack) >= cIack_frequency)
{
char aback[CHDRLEN];
@@ -1401,9 +1453,11 @@ fiprocess_packet (qdaemon, zhdr, zfirst, cfirst, zsecond, csecond, pfexit)
boolean fret;
iseq = IHDRWIN_GETSEQ (zhdr[IHDR_LOCAL]);
- DEBUG_MESSAGE2 (DEBUG_PROTO,
- "fiprocess_packet: Got DATA packet %d size %d",
- iseq, cfirst + csecond);
+ DEBUG_MESSAGE4 (DEBUG_PROTO,
+ "fiprocess_packet: Got DATA packet %d size %d local %d remote %d",
+ iseq, cfirst + csecond,
+ IHDRWIN_GETCHAN (zhdr[IHDR_REMOTE]),
+ IHDRWIN_GETCHAN (zhdr[IHDR_LOCAL]));
fret = fgot_data (qdaemon, zfirst, (size_t) cfirst,
zsecond, (size_t) csecond,
IHDRWIN_GETCHAN (zhdr[IHDR_REMOTE]),
@@ -1417,7 +1471,7 @@ fiprocess_packet (qdaemon, zhdr, zfirst, cfirst, zsecond, csecond, pfexit)
case SYNC:
{
- int ipack, iwin;
+ int ipack, iwin, cchans;
/* We accept a SYNC packet to adjust the packet and window
sizes at any time. */
@@ -1436,16 +1490,31 @@ fiprocess_packet (qdaemon, zhdr, zfirst, cfirst, zsecond, csecond, pfexit)
else
iwin = zsecond[2 - cfirst];
- DEBUG_MESSAGE2 (DEBUG_PROTO,
- "fiprocess_packet: Got SYNC packsize %d winsize %d",
- ipack, iwin);
+ /* The fourth byte in a SYNC packet is the number of channels
+ to use. This is optional. Switching the number of
+ channels in the middle of a conversation may cause
+ problems. */
+ if (cfirst + csecond <= 3)
+ cchans = 0;
+ else
+ {
+ if (cfirst > 3)
+ cchans = zfirst[3];
+ else
+ cchans = zsecond[3 - cfirst];
+ if (cchans > 0 && cchans < 8)
+ qdaemon->cchans = cchans;
+ }
+
+ DEBUG_MESSAGE3 (DEBUG_PROTO,
+ "fiprocess_packet: Got SYNC packsize %d winsize %d channels %d",
+ ipack, iwin, cchans);
if (iIforced_remote_packsize == 0
&& (iIalc_packsize == 0
|| ipack <= iIalc_packsize))
iIremote_packsize = ipack;
- if (iIforced_remote_winsize == 0)
- iIremote_winsize = iwin;
+ iIremote_winsize = iwin;
/* We increment a static variable to tell the initialization
code that a SYNC was received, and we set *pfexit to TRUE
@@ -1477,44 +1546,68 @@ fiprocess_packet (qdaemon, zhdr, zfirst, cfirst, zsecond, csecond, pfexit)
iseq = IHDRWIN_GETSEQ (zhdr[IHDR_LOCAL]);
- /* The timeout code will send a NAK for the packet the remote
- side wants. So we may see a NAK here for the packet we are
- about to send. */
- if (iseq == iIsendseq
- || (iIremote_winsize > 0
- && (CSEQDIFF (iseq, iIremote_ack) > iIremote_winsize
- || CSEQDIFF (iIsendseq, iseq) > iIremote_winsize)))
+ /* If the remote side times out while waiting for a packet, it
+ will send a NAK for the next packet it wants to see. If we
+ have not sent that packet yet, and we have no
+ unacknowledged data, it implies that the remote side has a
+ window full of data to send, which implies that our ACK has
+ been lost. Therefore, we send an ACK. */
+ if (iseq == iIsendseq &&
+ INEXTSEQ (iIremote_ack) == iIsendseq)
{
- DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
- "fiprocess_packet: Ignoring out of order NAK %d",
- iseq);
- return TRUE;
- }
+ char aback[CHDRLEN];
+
+ aback[IHDR_INTRO] = IINTRO;
+ aback[IHDR_LOCAL] = IHDRWIN_SET (0, 0);
+ aback[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, 0);
+ iIlocal_ack = iIrecseq;
+ aback[IHDR_CONTENTS1] = IHDRCON_SET1 (ACK, qdaemon->fcaller, 0);
+ aback[IHDR_CONTENTS2] = IHDRCON_SET2 (ACK, qdaemon->fcaller, 0);
+ aback[IHDR_CHECK] = IHDRCHECK_VAL (aback);
- DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
- "fiprocess_packet: Got NAK %d; resending packet",
- iseq);
+ DEBUG_MESSAGE1 (DEBUG_PROTO, "fiprocess_packet: Sending ACK %d",
+ iIrecseq);
- /* Update the received sequence number. */
- zsend = azIsendbuffers[iseq] + CHDROFFSET;
- if (IHDRWIN_GETSEQ (zsend[IHDR_REMOTE]) != iIrecseq)
+ return (*pfIsend) (qdaemon->qconn, aback, CHDRLEN, TRUE);
+ }
+ else
{
- int iremote;
+ if (iseq == iIsendseq
+ || (iIremote_winsize > 0
+ && (CSEQDIFF (iseq, iIremote_ack) > iIremote_winsize
+ || CSEQDIFF (iIsendseq, iseq) > iIremote_winsize)))
+ {
+ DEBUG_MESSAGE2 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fiprocess_packet: Ignoring out of order NAK %d (sendseq %d)",
+ iseq, iIsendseq);
+ return TRUE;
+ }
- iremote = IHDRWIN_GETCHAN (zsend[IHDR_REMOTE]);
- zsend[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, iremote);
- zsend[IHDR_CHECK] = IHDRCHECK_VAL (zsend);
- iIlocal_ack = iIrecseq;
- }
+ DEBUG_MESSAGE1 (DEBUG_PROTO | DEBUG_ABNORMAL,
+ "fiprocess_packet: Got NAK %d; resending packet",
+ iseq);
+
+ /* Update the received sequence number. */
+ zsend = azIsendbuffers[iseq] + CHDROFFSET;
+ if (IHDRWIN_GETSEQ (zsend[IHDR_REMOTE]) != iIrecseq)
+ {
+ int iremote;
+
+ iremote = IHDRWIN_GETCHAN (zsend[IHDR_REMOTE]);
+ zsend[IHDR_REMOTE] = IHDRWIN_SET (iIrecseq, iremote);
+ zsend[IHDR_CHECK] = IHDRCHECK_VAL (zsend);
+ iIlocal_ack = iIrecseq;
+ }
- ++cIresent_packets;
+ ++cIresent_packets;
- clen = CHDRCON_GETBYTES (zsend[IHDR_CONTENTS1],
- zsend[IHDR_CONTENTS2]);
+ clen = CHDRCON_GETBYTES (zsend[IHDR_CONTENTS1],
+ zsend[IHDR_CONTENTS2]);
- return (*pfIsend) (qdaemon->qconn, zsend,
- CHDRLEN + clen + (clen > 0 ? CCKSUMLEN : 0),
- TRUE);
+ return (*pfIsend) (qdaemon->qconn, zsend,
+ CHDRLEN + clen + (clen > 0 ? CCKSUMLEN : 0),
+ TRUE);
+ }
}
case SPOS:
diff --git a/gnu/libexec/uucp/uucico/protj.c b/gnu/libexec/uucp/uucico/protj.c
index 5717bb916dfb..e61b499f1c73 100644
--- a/gnu/libexec/uucp/uucico/protj.c
+++ b/gnu/libexec/uucp/uucico/protj.c
@@ -1,7 +1,7 @@
/* protj.c
The 'j' protocol.
- Copyright (C) 1992 Ian Lance Taylor
+ Copyright (C) 1992, 1994 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,19 +20,20 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char protj_rcsid[] = "$Id: protj.c,v 1.1 1993/08/05 18:27:14 conklin Exp $";
+const char protj_rcsid[] = "$Id: protj.c,v 1.2 1994/05/07 18:13:50 ache Exp $";
#endif
#include <ctype.h>
#include <errno.h>
#include "uudefs.h"
+#include "uuconf.h"
#include "conn.h"
#include "trans.h"
#include "system.h"
diff --git a/gnu/libexec/uucp/uucico/prott.c b/gnu/libexec/uucp/uucico/prott.c
index 44763958349a..bbbd7616eed6 100644
--- a/gnu/libexec/uucp/uucico/prott.c
+++ b/gnu/libexec/uucp/uucico/prott.c
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char prott_rcsid[] = "$Id: prott.c,v 1.1 1993/08/05 18:27:15 conklin Exp $";
+const char prott_rcsid[] = "$Id: prott.c,v 1.2 1994/05/07 18:13:51 ache Exp $";
#endif
#include "uudefs.h"
@@ -133,7 +133,8 @@ ftsendcmd (qdaemon, z, ilocal, iremote)
zalc = zbufalc (csend);
memcpy (zalc, z, clen);
- bzero (zalc + clen, csend - clen);
+ if (csend > clen)
+ bzero (zalc + clen, csend - clen);
fret = fsend_data (qdaemon->qconn, zalc, csend, TRUE);
ubuffree (zalc);
diff --git a/gnu/libexec/uucp/uucico/protz.c b/gnu/libexec/uucp/uucico/protz.c
index 6510df7d798e..c99ea8fb8d91 100644
--- a/gnu/libexec/uucp/uucico/protz.c
+++ b/gnu/libexec/uucp/uucico/protz.c
@@ -181,7 +181,7 @@
#include "uucp.h"
#if USE_RCS_ID
-const char protz_rcsid[] = "$Id: protz.c,v 1.1 1993/08/05 18:27:16 conklin Exp $";
+const char protz_rcsid[] = "$Id: protz.c,v 1.2 1994/05/07 18:13:52 ache Exp $";
#endif
#include <errno.h>
@@ -2084,7 +2084,7 @@ fifi:
cZheaders_received++;
break;
}
- DEBUG_MESSAGE2 (DEBUG_PROTO, "izrecv_hdr: %s, data = 0x%x",
+ DEBUG_MESSAGE2 (DEBUG_PROTO, "izrecv_hdr: %s, data = 0x%lx",
ZZHEADER_NAME(c), rclhdr (hdr));
return c;
diff --git a/gnu/libexec/uucp/uucico/rec.c b/gnu/libexec/uucp/uucico/rec.c
index b55d7f2c401f..c85647d56787 100644
--- a/gnu/libexec/uucp/uucico/rec.c
+++ b/gnu/libexec/uucp/uucico/rec.c
@@ -1,7 +1,7 @@
/* rec.c
Routines to receive a file.
- Copyright (C) 1991, 1992 Ian Lance Taylor
+ Copyright (C) 1991, 1992, 1993, 1994 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char rec_rcsid[] = "$Id: rec.c,v 1.1 1993/08/05 18:27:18 conklin Exp $";
+const char rec_rcsid[] = "$Id: rec.c,v 1.2 1994/05/07 18:13:55 ache Exp $";
#endif
#include <errno.h>
@@ -308,13 +308,22 @@ flocal_rec_send_request (qtrans, qdaemon)
boolean fret;
qinfo->ztemp = zsysdep_receive_temp (qdaemon->qsys, qinfo->zfile,
- (const char *) NULL);
+ (const char *) NULL,
+ (qdaemon->qproto->frestart
+ && (qdaemon->ifeatures
+ & FEATURE_RESTART) != 0));
if (qinfo->ztemp == NULL)
{
urrec_free (qtrans);
return FALSE;
}
+ qtrans->fcmd = TRUE;
+ qtrans->precfn = flocal_rec_await_reply;
+
+ if (! fqueue_receive (qdaemon, qtrans))
+ return FALSE;
+
/* Check the amount of free space available for both the temporary
file and the real file. */
cbytes = csysdep_bytes_free (qinfo->ztemp);
@@ -354,16 +363,11 @@ flocal_rec_send_request (qtrans, qdaemon)
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
qtrans->iremote);
ubuffree (zsend);
- if (! fret)
- {
- urrec_free (qtrans);
- return FALSE;
- }
- qtrans->fcmd = TRUE;
- qtrans->precfn = flocal_rec_await_reply;
+ if (! fret)
+ urrec_free (qtrans);
- return fqueue_receive (qdaemon, qtrans);
+ return fret;
}
/* This is called when a reply is received for the request. */
@@ -377,8 +381,8 @@ flocal_rec_await_reply (qtrans, qdaemon, zdata, cdata)
size_t cdata;
{
struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
- long crestart;
const char *zlog;
+ char *zend;
if (zdata[0] != 'R'
|| (zdata[1] != 'Y' && zdata[1] != 'N'))
@@ -407,6 +411,18 @@ flocal_rec_await_reply (qtrans, qdaemon, zdata, cdata)
zerr = "too large to receive now";
fnever = FALSE;
}
+ else if (zdata[2] == '9')
+ {
+ /* Remote has run out of channels. */
+ zerr = "too many channels for remote";
+ fnever = FALSE;
+
+ /* Drop one channel; using exactly one channel causes
+ slightly different behahaviour in a few places, so don't
+ decrement to one. */
+ if (qdaemon->cchans > 2)
+ --qdaemon->cchans;
+ }
else
zerr = "unknown reason";
@@ -423,16 +439,25 @@ flocal_rec_await_reply (qtrans, qdaemon, zdata, cdata)
/* The mode should have been sent as "RY 0%o". If it wasn't, we use
0666. */
qtrans->s.imode = (unsigned int) strtol ((char *) (zdata + 2),
- (char **) NULL, 8);
+ &zend, 8);
if (qtrans->s.imode == 0)
qtrans->s.imode = 0666;
+ /* If there is an M after the mode, the remote has requested a
+ hangup. */
+ if (*zend == 'M' && qdaemon->fmaster)
+ {
+ DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
+ "flocal_rec_await_reply: Remote has requested transfer of control");
+ qdaemon->fhangup_requested = TRUE;
+ }
+
/* Open the file to receive into. We just ignore any restart count,
since we have no way to tell it to the other side. SVR4 may have
some way to do this, but I don't know what it is. */
qtrans->e = esysdep_open_receive (qdaemon->qsys, qinfo->zfile,
(const char *) NULL, qinfo->ztemp,
- &crestart);
+ (long *) NULL);
if (! ffileisopen (qtrans->e))
return flocal_rec_fail (qtrans, &qtrans->s, qdaemon->qsys,
"cannot open file");
@@ -570,7 +595,15 @@ fremote_send_file_init (qdaemon, qcmd, iremote)
}
else
{
- zfile = zsysdep_local_file (qcmd->zto, qsys->uuconf_zpubdir);
+ boolean fbadname;
+
+ zfile = zsysdep_local_file (qcmd->zto, qsys->uuconf_zpubdir,
+ &fbadname);
+ if (zfile == NULL && fbadname)
+ {
+ ulog (LOG_ERROR, "%s: bad local file name", qcmd->zto);
+ return fremote_send_fail (qdaemon, qcmd, FAILURE_PERM, iremote);
+ }
if (zfile != NULL)
{
char *zadd;
@@ -603,7 +636,10 @@ fremote_send_file_init (qdaemon, qcmd, iremote)
}
}
- ztemp = zsysdep_receive_temp (qsys, zfile, qcmd->ztemp);
+ ztemp = zsysdep_receive_temp (qsys, zfile, qcmd->ztemp,
+ (qdaemon->qproto->frestart
+ && (qdaemon->ifeatures
+ & FEATURE_RESTART) != 0));
/* Adjust the number of bytes we are prepared to receive according
to the amount of free space we are supposed to leave available
@@ -646,7 +682,13 @@ fremote_send_file_init (qdaemon, qcmd, iremote)
/* Open the file to receive into. This may find an old copy of the
file, which will be used for file restart if the other side
supports it. */
- e = esysdep_open_receive (qsys, zfile, qcmd->ztemp, ztemp, &crestart);
+ crestart = -1;
+ e = esysdep_open_receive (qsys, zfile, qcmd->ztemp, ztemp,
+ ((qdaemon->qproto->frestart
+ && (qdaemon->ifeatures
+ & FEATURE_RESTART) != 0)
+ ? &crestart
+ : (long *) NULL));
if (! ffileisopen (e))
{
ubuffree (ztemp);
@@ -656,21 +698,16 @@ fremote_send_file_init (qdaemon, qcmd, iremote)
if (crestart > 0)
{
- if ((qdaemon->ifeatures & FEATURE_RESTART) == 0)
- crestart = -1;
- else
+ DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
+ "fremote_send_file_init: Restarting receive from %ld",
+ crestart);
+ if (! ffileseek (e, crestart))
{
- DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO,
- "fremote_send_file_init: Restarting receive from %ld",
- crestart);
- if (! ffileseek (e, crestart))
- {
- ulog (LOG_ERROR, "seek: %s", strerror (errno));
- (void) ffileclose (e);
- ubuffree (ztemp);
- ubuffree (zfile);
- return FALSE;
- }
+ ulog (LOG_ERROR, "seek: %s", strerror (errno));
+ (void) ffileclose (e);
+ ubuffree (ztemp);
+ ubuffree (zfile);
+ return FALSE;
}
}
@@ -705,8 +742,24 @@ fremote_send_file_init (qdaemon, qcmd, iremote)
else
zlog = qinfo->zfile;
}
- qtrans->zlog = zbufalc (sizeof "Receiving " + strlen (zlog));
+ qtrans->zlog = zbufalc (sizeof "Receiving ( bytes resume at )"
+ + strlen (zlog) + 50);
sprintf (qtrans->zlog, "Receiving %s", zlog);
+ if (crestart > 0 || qcmd->cbytes > 0)
+ {
+ strcat (qtrans->zlog, " (");
+ if (qcmd->cbytes > 0)
+ {
+ sprintf (qtrans->zlog + strlen (qtrans->zlog), "%ld bytes",
+ qcmd->cbytes);
+ if (crestart > 0)
+ strcat (qtrans->zlog, " ");
+ }
+ if (crestart > 0)
+ sprintf (qtrans->zlog + strlen (qtrans->zlog), "resume at %ld",
+ crestart);
+ strcat (qtrans->zlog, ")");
+ }
return fqueue_remote (qdaemon, qtrans);
}
@@ -719,8 +772,20 @@ fremote_send_reply (qtrans, qdaemon)
struct sdaemon *qdaemon;
{
struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
+ boolean fret;
char ab[50];
+ /* If the file has been completely received, we just want to send
+ the final confirmation. Otherwise, we must wait for the file
+ first. */
+ qtrans->psendfn = frec_file_send_confirm;
+ if (qinfo->freceived)
+ fret = fqueue_send (qdaemon, qtrans);
+ else
+ fret = fqueue_receive (qdaemon, qtrans);
+ if (! fret)
+ return FALSE;
+
ab[0] = qtrans->s.bcmd;
ab[1] = 'Y';
if (qtrans->ipos <= 0)
@@ -751,18 +816,9 @@ fremote_send_reply (qtrans, qdaemon)
urrec_free (qtrans);
return FALSE;
}
- if (fhandled)
- return TRUE;
}
- /* If the file has been completely received, we just want to send
- the final confirmation. Otherwise, we must wait for the file
- first. */
- qtrans->psendfn = frec_file_send_confirm;
- if (qinfo->freceived)
- return fqueue_send (qdaemon, qtrans);
- else
- return fqueue_receive (qdaemon, qtrans);
+ return TRUE;
}
/* If we can't receive a file, queue up a response to the remote
@@ -784,7 +840,7 @@ fremote_send_fail (qdaemon, qcmd, twhy, iremote)
/* If the protocol does not support multiple channels (cchans <= 1),
then we have essentially already received the entire file. */
- qinfo->freceived = qdaemon->qproto->cchans <= 1;
+ qinfo->freceived = qdaemon->cchans <= 1;
qtrans = qtransalc (qcmd);
qtrans->psendfn = fremote_send_fail_send;
@@ -807,6 +863,13 @@ fremote_send_fail_send (qtrans, qdaemon)
char ab[4];
boolean fret;
+ /* Wait for the end of file marker if we haven't gotten it yet. */
+ if (! qinfo->freceived)
+ {
+ if (! fqueue_receive (qdaemon, qtrans))
+ return FALSE;
+ }
+
ab[0] = qtrans->s.bcmd;
ab[1] = 'N';
@@ -840,13 +903,7 @@ fremote_send_fail_send (qtrans, qdaemon)
qinfo->fsent = TRUE;
- /* Wait for the end of file marker if we haven't gotten it yet. */
- if (! qinfo->freceived)
- {
- if (! fqueue_receive (qdaemon, qtrans))
- fret = FALSE;
- }
- else
+ if (qinfo->freceived)
{
xfree (qtrans->pinfo);
utransfree (qtrans);
@@ -902,6 +959,7 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
size_t cdata;
{
struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
+ char *zalc;
const char *zerr;
boolean fnever;
@@ -929,10 +987,13 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
fnever = FALSE;
+ zalc = NULL;
+
if (! ffileclose (qtrans->e))
{
zerr = strerror (errno);
ulog (LOG_ERROR, "%s: close: %s", qtrans->s.zto, zerr);
+ (void) remove (qinfo->ztemp);
}
else if (! fsysdep_move_file (qinfo->ztemp, qinfo->zfile, qinfo->fspool,
FALSE, ! qinfo->fspool,
@@ -940,7 +1001,49 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
? qtrans->s.zuser
: (const char *) NULL)))
{
- zerr = "could not move to final location";
+ long cspace;
+
+ /* Keep the temporary file if there is 1.5 times the amount of
+ required free space. This is just a random guess, to make an
+ unusual situtation potentially less painful. */
+ cspace = csysdep_bytes_free (qinfo->ztemp);
+ if (cspace == -1)
+ cspace = FREE_SPACE_DELTA;
+ cspace -= (qdaemon->qsys->uuconf_cfree_space
+ + qdaemon->qsys->uuconf_cfree_space / 2);
+ if (cspace < 0)
+ {
+ (void) remove (qinfo->ztemp);
+ zerr = "could not move to final location";
+ }
+ else
+ {
+ const char *az[20];
+ int i;
+
+ zalc = zbufalc (sizeof "could not move to final location (left as )"
+ + strlen (qinfo->ztemp));
+ sprintf (zalc, "could not move to final location (left as %s)",
+ qinfo->ztemp);
+ zerr = zalc;
+
+ i = 0;
+ az[i++] = "The file\n\t";
+ az[i++] = qinfo->ztemp;
+ az[i++] =
+ "\nwas saved because the move to the final location failed.\n";
+ az[i++] = "See the UUCP logs for more details.\n";
+ az[i++] = "The file transfer was from\n\t";
+ az[i++] = qdaemon->qsys->uuconf_zname;
+ az[i++] = "!";
+ az[i++] = qtrans->s.zfrom;
+ az[i++] = "\nto\n\t";
+ az[i++] = qtrans->s.zto;
+ az[i++] = "\nand was requested by\n\t";
+ az[i++] = qtrans->s.zuser;
+ az[i++] = "\n";
+ (void) fsysdep_mail (OWNER, "UUCP temporary file saved", i, az);
+ }
ulog (LOG_ERROR, "%s: %s", qinfo->zfile, zerr);
fnever = TRUE;
}
@@ -963,12 +1066,10 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
zerr = NULL;
}
- if (zerr != NULL)
- (void) remove (qinfo->ztemp);
-
ustats (zerr == NULL, qtrans->s.zuser, qdaemon->qsys->uuconf_zname,
FALSE, qtrans->cbytes, qtrans->isecs, qtrans->imicros,
qdaemon->fmaster);
+ qdaemon->creceived += qtrans->cbytes;
if (zerr == NULL)
{
@@ -1011,6 +1112,8 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
}
}
+ ubuffree (zalc);
+
/* If this is an execution request, we must create the execution
file itself. */
if (qtrans->s.bcmd == 'E' && zerr == NULL)
@@ -1040,7 +1143,10 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
uuxqt might pick up the file before we have finished writing
it. */
e = NULL;
- ztemp = zsysdep_receive_temp (qdaemon->qsys, zxqtfile, "D.0");
+ ztemp = zsysdep_receive_temp (qdaemon->qsys, zxqtfile, "D.0",
+ (qdaemon->qproto->frestart
+ && (qdaemon->ifeatures
+ & FEATURE_RESTART) != 0));
if (ztemp != NULL)
e = esysdep_fopen (ztemp, FALSE, FALSE, TRUE);
@@ -1077,7 +1183,10 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
{
if (! fsysdep_move_file (ztemp, zxqtfile, TRUE, FALSE, FALSE,
(const char *) NULL))
- fbad = TRUE;
+ {
+ (void) remove (ztemp);
+ fbad = TRUE;
+ }
}
ubuffree (zxqtfile);
@@ -1090,6 +1199,21 @@ frec_file_end (qtrans, qdaemon, zdata, cdata)
}
}
+ /* See if we should spawn a uuxqt process. */
+ if (zerr == NULL
+ && (qtrans->s.bcmd == 'E'
+ || (qinfo->fspool && qtrans->s.zto[0] == 'X')))
+ {
+ ++qdaemon->cxfiles_received;
+ if (qdaemon->irunuuxqt > 0
+ && qdaemon->cxfiles_received >= qdaemon->irunuuxqt)
+ {
+ if (fspawn_uuxqt (TRUE, qdaemon->qsys->uuconf_zname,
+ qdaemon->zconfig))
+ qdaemon->cxfiles_received = 0;
+ }
+ }
+
/* Prepare to send the completion string to the remote system. If
we have not yet replied to the remote send request, we leave the
transfer structure on the remote queue. Otherwise we add it to
diff --git a/gnu/libexec/uucp/uucico/send.c b/gnu/libexec/uucp/uucico/send.c
index 8e2c55ef3724..60c3924ec694 100644
--- a/gnu/libexec/uucp/uucico/send.c
+++ b/gnu/libexec/uucp/uucico/send.c
@@ -1,7 +1,7 @@
/* send.c
Routines to send a file.
- Copyright (C) 1991, 1992 Ian Lance Taylor
+ Copyright (C) 1991, 1992, 1993, 1994 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char send_rcsid[] = "$Id: send.c,v 1.1 1993/08/05 18:27:19 conklin Exp $";
+const char send_rcsid[] = "$Id: send.c,v 1.2 1994/05/07 18:13:57 ache Exp $";
#endif
#include <errno.h>
@@ -51,7 +51,9 @@ struct ssendinfo
boolean flocal;
/* TRUE if this is a spool directory file. */
boolean fspool;
- /* TRUE if the file has been completely sent. */
+ /* TRUE if the file has been completely sent. Also used in
+ flocal_send_cancelled to mean that the file send will never
+ succeed. */
boolean fsent;
/* Execution file for sending an unsupported E request. */
char *zexec;
@@ -62,7 +64,7 @@ struct ssendinfo
static void usfree_send P((struct stransfer *qtrans));
static boolean flocal_send_fail P((struct stransfer *qtrans,
struct scmd *qcmd,
- const struct uuconf_system *qsys,
+ struct sdaemon *qdaemon,
const char *zwhy));
static boolean flocal_send_request P((struct stransfer *qtrans,
struct sdaemon *qdaemon));
@@ -150,10 +152,9 @@ usfree_send (qtrans)
flocal_send_request.
If flocal_send_await_reply is called before the entire file has
- been sent: if it gets an SN, it calls flocal_send_cancelled to send
- an empty data block to inform the remote system that the file
- transfer has stopped. If it gets a file position request, it must
- adjust the file position accordingly.
+ been sent: if it gets an SN, it sets the file position to the end
+ and arranges to call flocal_send_cancelled. If it gets a file
+ position request, it must adjust the file position accordingly.
If flocal_send_await_reply is called after the entire file has been
sent: if it gets an SN, it can simply delete the request. It can
@@ -197,7 +198,7 @@ flocal_send_file_init (qdaemon, qcmd)
is possible, but it might have changed since then. */
if (! qsys->uuconf_fcall_transfer
&& ! qsys->uuconf_fcalled_transfer)
- return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
+ return flocal_send_fail ((struct stransfer *) NULL, qcmd, qdaemon,
"not permitted to transfer files");
/* We can't do the request now, but it may get done later. */
@@ -214,7 +215,7 @@ flocal_send_file_init (qdaemon, qcmd)
qsys->uuconf_pzlocal_send,
qsys->uuconf_zpubdir, TRUE,
TRUE, qcmd->zuser))
- return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
+ return flocal_send_fail ((struct stransfer *) NULL, qcmd, qdaemon,
"not permitted to send");
zfile = zbufcpy (qcmd->zfrom);
}
@@ -234,12 +235,13 @@ flocal_send_file_init (qdaemon, qcmd)
{
ubuffree (zfile);
if (cbytes != -1)
- return FALSE;
+ return flocal_send_fail ((struct stransfer *) NULL, qcmd, qdaemon,
+ "can not get size");
/* A cbytes value of -1 means that the file does not exist.
This can happen legitimately if it has already been sent from
the spool directory. */
if (! fspool)
- return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
+ return flocal_send_fail ((struct stransfer *) NULL, qcmd, qdaemon,
"does not exist");
(void) fsysdep_did_work (qcmd->pseq);
return TRUE;
@@ -264,7 +266,7 @@ flocal_send_file_init (qdaemon, qcmd)
if (qdaemon->cmax_ever != -1
&& qdaemon->cmax_ever < qcmd->cbytes)
- return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
+ return flocal_send_fail ((struct stransfer *) NULL, qcmd, qdaemon,
"too large to send");
return TRUE;
@@ -280,7 +282,7 @@ flocal_send_file_init (qdaemon, qcmd)
qinfo->zmail = zbufcpy (qcmd->zuser);
qinfo->zfile = zfile;
qinfo->cbytes = cbytes;
- qinfo->flocal = TRUE;
+ qinfo->flocal = strchr (qcmd->zuser, '!') == NULL;
qinfo->fspool = fspool;
qinfo->fsent = FALSE;
qinfo->zexec = NULL;
@@ -296,32 +298,48 @@ flocal_send_file_init (qdaemon, qcmd)
this reports an error to the log file and to the user. */
static boolean
-flocal_send_fail (qtrans, qcmd, qsys, zwhy)
+flocal_send_fail (qtrans, qcmd, qdaemon, zwhy)
struct stransfer *qtrans;
struct scmd *qcmd;
- const struct uuconf_system *qsys;
+ struct sdaemon *qdaemon;
const char *zwhy;
{
if (zwhy != NULL)
{
+ const char *zfrom;
char *zfree;
+ const char *ztemp;
if (qcmd->bcmd != 'E')
- zfree = NULL;
+ {
+ zfrom = qcmd->zfrom;
+ zfree = NULL;
+ }
else
{
- zfree = zbufalc (sizeof "Execution of \"\": "
- + strlen (qcmd->zcmd)
- + strlen (zwhy));
- sprintf (zfree, "Execution of \"%s\": %s", qcmd->zcmd, zwhy);
- zwhy = zfree;
+ zfree = zbufalc (strlen (qcmd->zfrom)
+ + sizeof " (execution of \"\")"
+ + strlen (qcmd->zcmd));
+ sprintf (zfree, "%s (execution of \"%s\")", qcmd->zfrom,
+ qcmd->zcmd);
+ zfrom = zfree;
}
- ulog (LOG_ERROR, "%s: %s", qcmd->zfrom, zwhy);
+ ulog (LOG_ERROR, "%s: %s", zfrom, zwhy);
+
+ /* We only save the temporary file if this is a request from the
+ local system; otherwise a remote system could launch a denial
+ of service attack by filling up the .Preserve directory
+ (local users have much simpler methods for this type of
+ denial of service attack, so there is little point to using a
+ more sophisticated scheme). */
+ if (strchr (qcmd->zuser, '!') == NULL)
+ ztemp = zsysdep_save_temp_file (qcmd->pseq);
+ else
+ ztemp = NULL;
(void) fmail_transfer (FALSE, qcmd->zuser, (const char *) NULL,
- zwhy, qcmd->zfrom, (const char *) NULL,
- qcmd->zto, qsys->uuconf_zname,
- zsysdep_save_temp_file (qcmd->pseq));
+ zwhy, zfrom, (const char *) NULL,
+ qcmd->zto, qdaemon->qsys->uuconf_zname, ztemp);
ubuffree (zfree);
}
@@ -353,9 +371,37 @@ flocal_send_request (qtrans, qdaemon)
/* Make sure the file meets any remote size restrictions. */
if (qdaemon->cmax_receive != -1
&& qdaemon->cmax_receive < qinfo->cbytes)
- return flocal_send_fail (qtrans, &qtrans->s, qdaemon->qsys,
+ return flocal_send_fail (qtrans, &qtrans->s, qdaemon,
"too large for receiver");
+ /* Make sure the file still exists--it may have been removed between
+ the conversation startup and now. After we have sent over the S
+ command we must give an error if we can't find the file. */
+ if (! fsysdep_file_exists (qinfo->zfile))
+ {
+ (void) fsysdep_did_work (qtrans->s.pseq);
+ usfree_send (qtrans);
+ return TRUE;
+ }
+
+ /* If we are using a protocol which can make multiple channels, then
+ we can open and send the file whenever we are ready. This is
+ because we will be able to distinguish the response by the
+ channel it is directed to. This assumes that every protocol
+ which supports multiple channels also supports sending the file
+ position in mid-stream, since otherwise we would not be able to
+ restart files. */
+ qtrans->fcmd = TRUE;
+ qtrans->psendfn = flocal_send_open_file;
+ qtrans->precfn = flocal_send_await_reply;
+
+ if (qdaemon->cchans > 1)
+ fret = fqueue_send (qdaemon, qtrans);
+ else
+ fret = fqueue_receive (qdaemon, qtrans);
+ if (! fret)
+ return FALSE;
+
/* Construct the notify string to send. If we are going to send a
size or an execution command, it must be non-empty. */
znotify = qtrans->s.znotify;
@@ -452,27 +498,11 @@ flocal_send_request (qtrans, qdaemon)
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
qtrans->iremote);
ubuffree (zsend);
- if (! fret)
- {
- usfree_send (qtrans);
- return FALSE;
- }
- /* If we are using a protocol which can make multiple channels, then
- we can open and send the file whenever we are ready. This is
- because we will be able to distinguish the response by the
- channel it is directed to. This assumes that every protocol
- which supports multiple channels also supports sending the file
- position in mid-stream, since otherwise we would not be able to
- restart files. */
- qtrans->fcmd = TRUE;
- qtrans->psendfn = flocal_send_open_file;
- qtrans->precfn = flocal_send_await_reply;
+ if (! fret)
+ usfree_send (qtrans);
- if (qdaemon->qproto->cchans > 1)
- return fqueue_send (qdaemon, qtrans);
- else
- return fqueue_receive (qdaemon, qtrans);
+ return fret;
}
/* This is called when a reply is received for the send request. As
@@ -535,21 +565,36 @@ flocal_send_await_reply (qtrans, qdaemon, zdata, cdata)
is no need to resend the file. */
zerr = NULL;
}
+ else if (zdata[2] == '9')
+ {
+ /* Remote has run out of channels. */
+ zerr = "too many channels for remote";
+ fnever = FALSE;
+
+ /* Drop one channel; using exactly one channel causes
+ slightly different behahaviour in a few places, so don't
+ decrement to one. */
+ if (qdaemon->cchans > 2)
+ --qdaemon->cchans;
+ }
else
zerr = "unknown reason";
- if (! fnever)
+ if (! fnever
+ || (qtrans->s.bcmd == 'E'
+ && (qdaemon->ifeatures & FEATURE_EXEC) == 0
+ && qinfo->zexec == NULL))
{
if (qtrans->s.bcmd == 'E')
- ulog (LOG_ERROR, "Execution of \"%s\": %s", qtrans->s.zcmd,
- zerr);
+ ulog (LOG_ERROR, "%s (execution of \"%s\"): %s",
+ qtrans->s.zfrom, qtrans->s.zcmd, zerr);
else
ulog (LOG_ERROR, "%s: %s", qtrans->s.zfrom, zerr);
}
else
{
if (! flocal_send_fail ((struct stransfer *) NULL, &qtrans->s,
- qdaemon->qsys, zerr))
+ qdaemon, zerr))
return FALSE;
}
@@ -558,16 +603,39 @@ flocal_send_await_reply (qtrans, qdaemon, zdata, cdata)
the remote side knows that we have finished sending the file
data. If we have already sent the entire file, there will be
no confusion. */
- if (qdaemon->qproto->cchans == 1 || qinfo->fsent)
+ if (qdaemon->cchans == 1 || qinfo->fsent)
{
+ /* If we are breaking a 'E' command into two 'S' commands,
+ and that was for the first 'S' command, we still have to
+ send the second one. */
+ if (fnever
+ && qtrans->s.bcmd == 'E'
+ && (qdaemon->ifeatures & FEATURE_EXEC) == 0
+ && qinfo->zexec == NULL)
+ return fsend_exec_file_init (qtrans, qdaemon);
+
usfree_send (qtrans);
return TRUE;
}
else
{
+ /* Seek to the end of the file so that the next read will
+ send end of file. We have to be careful here, because we
+ may have actually already sent end of file--we could be
+ being called because of data received while the end of
+ file block was sent. */
+ if (! ffileseekend (qtrans->e))
+ {
+ ulog (LOG_ERROR, "seek to end: %s", strerror (errno));
+ usfree_send (qtrans);
+ return FALSE;
+ }
qtrans->psendfn = flocal_send_cancelled;
qtrans->precfn = NULL;
- qtrans->fsendfile = FALSE;
+
+ /* Reuse fsent to pass fnever to flocal_send_cancelled. */
+ qinfo->fsent = fnever;
+
return fqueue_send (qdaemon, qtrans);
}
}
@@ -603,7 +671,7 @@ flocal_send_await_reply (qtrans, qdaemon, zdata, cdata)
qtrans->precfn = fsend_await_confirm;
if (qinfo->fsent)
return fqueue_receive (qdaemon, qtrans);
- else if (qdaemon->qproto->cchans <= 1)
+ else if (qdaemon->cchans <= 1)
return fqueue_send (qdaemon, qtrans);
else
return TRUE;
@@ -638,7 +706,9 @@ flocal_send_open_file (qtrans, qdaemon)
qtrans->s.zfrom, (const char *) NULL,
qtrans->s.zto,
qdaemon->qsys->uuconf_zname,
- zsysdep_save_temp_file (qtrans->s.pseq));
+ (qinfo->flocal
+ ? zsysdep_save_temp_file (qtrans->s.pseq)
+ : (const char *) NULL));
(void) fsysdep_did_work (qtrans->s.pseq);
usfree_send (qtrans);
@@ -688,8 +758,15 @@ flocal_send_open_file (qtrans, qdaemon)
sprintf (zalc, "%s (%s)", qtrans->s.zcmd, qtrans->s.zfrom);
zsend = zalc;
}
- qtrans->zlog = zbufalc (sizeof "Sending " + strlen (zsend));
- sprintf (qtrans->zlog, "Sending %s", zsend);
+
+ qtrans->zlog = zbufalc (sizeof "Sending ( bytes resume at )"
+ + strlen (zsend) + 50);
+ sprintf (qtrans->zlog, "Sending %s (%ld bytes", zsend, qinfo->cbytes);
+ if (qtrans->ipos > 0)
+ sprintf (qtrans->zlog + strlen (qtrans->zlog), " resume at %ld",
+ qtrans->ipos);
+ strcat (qtrans->zlog, ")");
+
ubuffree (zalc);
}
@@ -698,7 +775,8 @@ flocal_send_open_file (qtrans, qdaemon)
boolean fhandled;
if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, TRUE,
- qinfo->cbytes, &fhandled))
+ qinfo->cbytes - qtrans->ipos,
+ &fhandled))
{
usfree_send (qtrans);
return FALSE;
@@ -719,32 +797,29 @@ flocal_send_open_file (qtrans, qdaemon)
return fqueue_send (qdaemon, qtrans);
}
-/* Cancel a file send by sending an empty buffer. This is only called
- for a protocol which supports multiple channels. It is needed
- so that both systems agree as to when a channel is no longer
- needed. */
+/* Cancel a file send. This is only called for a protocol which
+ supports multiple channels. It is needed so that both systems
+ agree as to when a channel is no longer needed. */
static boolean
flocal_send_cancelled (qtrans, qdaemon)
struct stransfer *qtrans;
struct sdaemon *qdaemon;
{
- char *zdata;
- size_t cdata;
- boolean fret;
-
- zdata = (*qdaemon->qproto->pzgetspace) (qdaemon, &cdata);
- if (zdata == NULL)
- {
- usfree_send (qtrans);
- return FALSE;
- }
+ struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
+
+ /* If we are breaking a 'E' command into two 'S' commands, and that
+ was for the first 'S' command, and the first 'S' command will
+ never be sent (passed as qinfo->fsent), we still have to send the
+ second one. */
+ if (qinfo->fsent
+ && qtrans->s.bcmd == 'E'
+ && (qdaemon->ifeatures & FEATURE_EXEC) == 0
+ && qinfo->zexec == NULL)
+ return fsend_exec_file_init (qtrans, qdaemon);
- fret = (*qdaemon->qproto->pfsenddata) (qdaemon, zdata, (size_t) 0,
- qtrans->ilocal, qtrans->iremote,
- qtrans->ipos);
usfree_send (qtrans);
- return fret;
+ return TRUE;
}
/* A remote request to receive a file (meaning that we have to send a
@@ -765,6 +840,7 @@ fremote_rec_file_init (qdaemon, qcmd, iremote)
{
const struct uuconf_system *qsys;
char *zfile;
+ boolean fbadname;
long cbytes;
unsigned int imode;
openfile_t e;
@@ -786,7 +862,12 @@ fremote_rec_file_init (qdaemon, qcmd, iremote)
return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
}
- zfile = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir);
+ zfile = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir, &fbadname);
+ if (zfile == NULL && fbadname)
+ {
+ ulog (LOG_ERROR, "%s: bad local file name", qcmd->zfrom);
+ return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
+ }
if (zfile != NULL)
{
char *zbased;
@@ -875,8 +956,24 @@ fremote_rec_reply (qtrans, qdaemon)
struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
char absend[50];
- sprintf (absend, "RY 0%o 0x%lx", qtrans->s.imode,
- (unsigned long) qinfo->cbytes);
+ qtrans->fsendfile = TRUE;
+ qtrans->psendfn = fsend_file_end;
+ qtrans->precfn = fsend_await_confirm;
+
+ if (! fqueue_send (qdaemon, qtrans))
+ return FALSE;
+
+ /* We send the file size because SVR4 UUCP does. We don't look for
+ it. We send a trailing M if we want to request a hangup. We
+ send it both after the mode and at the end of the entire string;
+ I don't know where programs look for it. */
+ if (qdaemon->frequest_hangup)
+ DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
+ "fremote_rec_reply: Requesting remote to transfer control");
+ sprintf (absend, "RY 0%o%s 0x%lx%s", qtrans->s.imode,
+ qdaemon->frequest_hangup ? "M" : "",
+ (unsigned long) qinfo->cbytes,
+ qdaemon->frequest_hangup ? "M" : "");
if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, absend, qtrans->ilocal,
qtrans->iremote))
{
@@ -885,8 +982,10 @@ fremote_rec_reply (qtrans, qdaemon)
return FALSE;
}
- qtrans->zlog = zbufalc (sizeof "Sending " + strlen (qtrans->s.zfrom));
- sprintf (qtrans->zlog, "Sending %s", qtrans->s.zfrom);
+ qtrans->zlog = zbufalc (sizeof "Sending ( bytes) "
+ + strlen (qtrans->s.zfrom) + 25);
+ sprintf (qtrans->zlog, "Sending %s (%ld bytes)", qtrans->s.zfrom,
+ qinfo->cbytes);
if (qdaemon->qproto->pffile != NULL)
{
@@ -898,16 +997,9 @@ fremote_rec_reply (qtrans, qdaemon)
usfree_send (qtrans);
return FALSE;
}
-
- if (fhandled)
- return TRUE;
}
- qtrans->fsendfile = TRUE;
- qtrans->psendfn = fsend_file_end;
- qtrans->precfn = fsend_await_confirm;
-
- return fqueue_send (qdaemon, qtrans);
+ return TRUE;
}
/* If we can't send a file as requested by the remote system, queue up
@@ -1057,6 +1149,7 @@ fsend_await_confirm (qtrans, qdaemon, zdata, cdata)
ustats (zerr == NULL, qtrans->s.zuser, qdaemon->qsys->uuconf_zname,
TRUE, qtrans->cbytes, qtrans->isecs, qtrans->imicros,
qdaemon->fmaster);
+ qdaemon->csent += qtrans->cbytes;
if (zerr == NULL)
{
diff --git a/gnu/libexec/uucp/uucico/time.c b/gnu/libexec/uucp/uucico/time.c
index 4305e990e245..727a4c8066c6 100644
--- a/gnu/libexec/uucp/uucico/time.c
+++ b/gnu/libexec/uucp/uucico/time.c
@@ -1,7 +1,7 @@
/* time.c
Routines to deal with UUCP time spans.
- Copyright (C) 1991, 1992 Ian Lance Taylor
+ Copyright (C) 1991, 1992, 1993 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,18 +20,20 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char time_rcsid[] = "$Id: time.c,v 1.1 1993/08/05 18:27:20 conklin Exp $";
+const char time_rcsid[] = "$Id: time.c,v 1.2 1994/05/07 18:13:58 ache Exp $";
#endif
#include <ctype.h>
-#if HAVE_TIME_H
+#if TM_IN_SYS_TIME
+#include <sys/time.h>
+#else
#include <time.h>
#endif
diff --git a/gnu/libexec/uucp/uucico/trans.c b/gnu/libexec/uucp/uucico/trans.c
index 2bb4d228195c..f53aa3b1244f 100644
--- a/gnu/libexec/uucp/uucico/trans.c
+++ b/gnu/libexec/uucp/uucico/trans.c
@@ -1,7 +1,7 @@
/* trans.c
Routines to handle file transfers.
- Copyright (C) 1992 Ian Lance Taylor
+ Copyright (C) 1992, 1993 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char trans_rcsid[] = "$Id: trans.c,v 1.1 1993/08/05 18:27:21 conklin Exp $";
+const char trans_rcsid[] = "$Id: trans.c,v 1.2 1994/05/07 18:13:59 ache Exp $";
#endif
#include <errno.h>
@@ -233,7 +233,39 @@ fqueue_send (qdaemon, qtrans)
ulog (LOG_FATAL, "fqueue_send: Bad call");
#endif
utdequeue (qtrans);
- utqueue (&qTsend, qtrans, FALSE);
+
+ /* Sort the send queue to always send commands before files, and to
+ sort jobs by grade. */
+ if (qTsend == NULL)
+ utqueue (&qTsend, qtrans, FALSE);
+ else
+ {
+ register struct stransfer *q;
+ boolean ffirst;
+
+ ffirst = TRUE;
+ q = qTsend;
+ do
+ {
+ if (! qtrans->fsendfile && q->fsendfile)
+ break;
+ if ((! qtrans->fsendfile || q->fsendfile)
+ && UUCONF_GRADE_CMP (qtrans->s.bgrade, q->s.bgrade) < 0)
+ break;
+
+ ffirst = FALSE;
+ q = q->qnext;
+ }
+ while (q != qTsend);
+
+ qtrans->qnext = q;
+ qtrans->qprev = q->qprev;
+ q->qprev = qtrans;
+ qtrans->qprev->qnext = qtrans;
+ if (ffirst)
+ qTsend = qtrans;
+ qtrans->pqqueue = &qTsend;
+ }
/* Since we're now going to wait to send data, don't charge this
transfer for receive time. */
@@ -273,7 +305,7 @@ utchanalc (qdaemon, qtrans)
do
{
++iTchan;
- if (iTchan > qdaemon->qproto->cchans)
+ if (iTchan > qdaemon->cchans)
iTchan = 1;
}
while (aqTchan[iTchan] != NULL);
@@ -388,6 +420,7 @@ utransfree (q)
}
#if DEBUG > 0
+ q->e = EFILECLOSED;
q->zcmd = NULL;
q->s.zfrom = NULL;
q->s.zto = NULL;
@@ -625,18 +658,12 @@ static boolean
fcheck_queue (qdaemon)
struct sdaemon *qdaemon;
{
- int cchans;
-
/* Only check if we are the master, or if there are multiple
channels, or if we aren't already trying to get the other side to
hang up. Otherwise, there's nothing we can do with any new jobs
we might find. */
- if ((qdaemon->ireliable & UUCONF_RELIABLE_FULLDUPLEX) == 0)
- cchans = 1;
- else
- cchans = qdaemon->qproto->cchans;
if (qdaemon->fmaster
- || cchans > 1
+ || qdaemon->cchans > 1
|| ! qdaemon->frequest_hangup)
{
boolean fany;
@@ -649,7 +676,7 @@ fcheck_queue (qdaemon)
/* If we found something to do, and we're not the master, and we
don't have multiple channels to send new jobs over, try to
get the other side to hang up. */
- if (fany && ! qdaemon->fmaster && cchans <= 1)
+ if (fany && ! qdaemon->fmaster && qdaemon->cchans <= 1)
qdaemon->frequest_hangup = TRUE;
}
@@ -663,17 +690,8 @@ boolean
floop (qdaemon)
struct sdaemon *qdaemon;
{
- int cchans;
boolean fret;
- /* If we are using a half-duplex line, act as though we have only a
- single channel; otherwise we might start a send and a receive at
- the same time. */
- if ((qdaemon->ireliable & UUCONF_RELIABLE_FULLDUPLEX) == 0)
- cchans = 1;
- else
- cchans = qdaemon->qproto->cchans;
-
fret = TRUE;
while (! qdaemon->fhangup)
@@ -759,9 +777,9 @@ floop (qdaemon)
/* If we are the master, or if we have multiple channels, try to
queue up additional local jobs. */
- if (qdaemon->fmaster || cchans > 1)
+ if (qdaemon->fmaster || qdaemon->cchans > 1)
{
- while (qTlocal != NULL && cTchans < cchans)
+ while (qTlocal != NULL && cTchans < qdaemon->cchans)
{
/* We have room for an additional channel. */
q = qTlocal;
@@ -821,11 +839,14 @@ floop (qdaemon)
q->zlog = NULL;
}
- /* We can read the file in a tight loop until qTremote
- changes or until we have transferred the entire file.
- We can disregard any changes to qTlocal since we
- already have something to send anyhow. */
- while (qTremote == NULL)
+ /* We can read the file in a tight loop until we have a
+ command to send, or the file send has been cancelled,
+ or we have a remote job to deal with. We can
+ disregard any changes to qTlocal since we already
+ have something to send anyhow. */
+ while (q == qTsend
+ && q->fsendfile
+ && qTremote == NULL)
{
char *zdata;
size_t cdata;
@@ -865,11 +886,6 @@ floop (qdaemon)
break;
}
- /* It is possible that this transfer has just been
- cancelled. */
- if (q != qTsend || ! q->fsendfile)
- break;
-
if (cdata == 0)
{
/* We must update the time now, because this
@@ -978,7 +994,6 @@ fgot_data (qdaemon, zfirst, cfirst, zsecond, csecond, ilocal, iremote, ipos,
else
{
/* Get the transfer structure this data is intended for. */
-
q = qtchan (ilocal);
}
@@ -1014,7 +1029,8 @@ fgot_data (qdaemon, zfirst, cfirst, zsecond, csecond, ilocal, iremote, ipos,
else
cnew = cfirst;
znew = zbufalc (q->ccmd + cnew + 1);
- memcpy (znew, q->zcmd, q->ccmd);
+ if (q->ccmd > 0)
+ memcpy (znew, q->zcmd, q->ccmd);
memcpy (znew + q->ccmd, zfirst, cnew);
znew[q->ccmd + cnew] = '\0';
ubuffree (q->zcmd);
@@ -1206,6 +1222,12 @@ ftadd_cmd (qdaemon, z, clen, iremote, flast)
return TRUE;
}
+ /* Some systems seem to sometimes send garbage at the end of the
+ command. Avoid interpreting it as a size if sizes are not
+ supported. */
+ if ((qdaemon->ifeatures & FEATURE_SIZES) == 0)
+ s.cbytes = -1;
+
if (s.bcmd != 'H' && s.bcmd != 'Y' && s.bcmd != 'N')
ulog_user (s.zuser);
else
@@ -1391,9 +1413,15 @@ ufailed (qdaemon)
{
if ((q->fsendfile || q->frecfile)
&& q->cbytes > 0)
- ustats (FALSE, q->s.zuser, qdaemon->qsys->uuconf_zname,
- q->fsendfile, q->cbytes, q->isecs, q->imicros,
- FALSE);
+ {
+ ustats (FALSE, q->s.zuser, qdaemon->qsys->uuconf_zname,
+ q->fsendfile, q->cbytes, q->isecs, q->imicros,
+ FALSE);
+ if (q->fsendfile)
+ qdaemon->csent += q->cbytes;
+ else
+ qdaemon->creceived += q->cbytes;
+ }
if (q->frecfile)
(void) frec_discard_temp (qdaemon, q);
q = q->qnext;
@@ -1408,9 +1436,15 @@ ufailed (qdaemon)
{
if ((q->fsendfile || q->frecfile)
&& q->cbytes > 0)
- ustats (FALSE, q->s.zuser, qdaemon->qsys->uuconf_zname,
- q->fsendfile, q->cbytes, q->isecs, q->imicros,
- FALSE);
+ {
+ ustats (FALSE, q->s.zuser, qdaemon->qsys->uuconf_zname,
+ q->fsendfile, q->cbytes, q->isecs, q->imicros,
+ FALSE);
+ if (q->fsendfile)
+ qdaemon->csent += q->cbytes;
+ else
+ qdaemon->creceived += q->cbytes;
+ }
if (q->frecfile)
(void) frec_discard_temp (qdaemon, q);
q = q->qnext;
diff --git a/gnu/libexec/uucp/uucico/uucico.8 b/gnu/libexec/uucp/uucico/uucico.8
index ccc93afab563..3915e82f163c 100644
--- a/gnu/libexec/uucp/uucico/uucico.8
+++ b/gnu/libexec/uucp/uucico/uucico.8
@@ -1,5 +1,5 @@
-''' $Id: uucico.8,v 1.1.2.1 1994/05/01 16:02:47 jkh Exp $
-.TH uucico 8 "Taylor UUCP 1.04"
+''' $Id: uucico.8,v 1.3 1994/05/07 18:14:01 ache Exp $
+.TH uucico 8 "Taylor UUCP 1.05"
.SH NAME
uucico \- UUCP file transfer daemon
.SH SYNOPSIS
@@ -23,17 +23,17 @@ entries in the
.I crontab
table(s).
-When invoked with the
-.B \-r1
-option or the
-.B \-s
+When invoked with
+.B \-r1,
+.B \-\-master,
+.B \-s,
+.B \-\-system,
or
-.B \-S
-option, the daemon will place a call to a remote system, running in
-master mode.
-Otherwise the daemon will start in slave mode, accepting a
-call from a remote system. Typically a special login name will be set
-up for UUCP which automatically invokes
+.B \-S,
+the daemon will place a call to a remote system, running in master
+mode. Otherwise the daemon will start in slave mode, accepting a call
+from a remote system. Typically a special login name will be set up
+for UUCP which automatically invokes
.I uucico
when a call is made.
@@ -43,6 +43,8 @@ terminates, it invokes the
.I uuxqt
(8) daemon, unless the
.B \-q
+or
+.B \-\-nouuxqt
option is given;
.I uuxqt
(8) executes any work orders created by
@@ -54,29 +56,48 @@ If a call fails,
.I uucico
will normally refuse to retry the
call until a certain (configurable) amount of time
-has passed. This may be overridden by the
-.B -f
-or the
+has passed. This may be overriden by the
+.B -f,
+.B --force,
+or
.B -S
option.
The
-.B \-l
+.B \-l,
+.B \-\-prompt,
+.B \-e,
or
-.B \-e
-option may be used to force
+.B \-\-loop
+options may be used to force
.I uucico
to produce its own prompts of "login: " and "Password:". When another
-daemon calls in, it will see these prompts and log in as usual; the
-login name and password will be checked against a separate list kept
-specially for
+daemon calls in, it will see these prompts and log in as usual. The
+login name and password will normally be checked against a separate
+list kept specially for
.I uucico
rather than the
.I /etc/passwd
+file; it is possible on some systems to direct
+.I uucico
+to use the
+.I /etc/passwd
file. The
.B \-l
-option will prompt once and then exit. The
+or
+.B \--prompt
+option will prompt once and then exit; in this mode the UUCP
+administrator or the superuser may use the
+.B \-u
+or
+.B \--login
+option to force a login name, in which case
+.I uucico
+will not prompt for one.
+The
.B \-e
+or
+.B \--loop
option will prompt again after the first session is over; in this mode
.I uucico
will permanently control a port.
@@ -87,9 +108,13 @@ receives a SIGQUIT, SIGTERM or SIGPIPE signal, it will cleanly abort
any current conversation with a remote system and exit. If it
receives a SIGHUP signal it will abort any current conversation, but
will continue to place calls to (if invoked with
-.B \-r1)
+.B \-r1
+or
+.B \-\-master)
and accept calls from (if invoked with
-.B \-e)
+.B \-e
+or
+.B \-\-loop)
other systems. If it receives a
SIGINT signal it will finish the current conversation, but will not
place or accept any more calls.
@@ -97,72 +122,91 @@ place or accept any more calls.
The following options may be given to
.I uucico.
.TP 5
-.B \-r1
+.B \-r1, \-\-master
Start in master mode (call out to a system); implied by
-.B \-s
+.B \-s,
+.B \-\-system,
or
.B \-S.
If no system is specified, call any system for which work is waiting
to be done.
.TP 5
-.B \-r0
+.B \-r0, \-\-slave
Start in slave mode. This is the default.
.TP 5
-.B \-s system
+.B \-s system, \-\-system system
Call the named system.
.TP 5
.B \-S system
-Call the named system, ignoring any required wait.
+Call the named system, ignoring any required wait. This is equivalent
+to
+.B \-s system \-f.
.TP 5
-.B \-f
+.B \-f, \-\-force
Ignore any required wait for any systems to be called.
.TP 5
-.B \-l
+.B \-l, \-\-prompt
Prompt for login name and password using "login: " and "Password:".
This allows
.I uucico
to be easily run from
.I inetd
(8). The login name and password are checked against the UUCP
-password file, which has no connection to the file
+password file, which probably has no connection to the file
.I /etc/passwd.
+The
+.B \-\-login
+option may be used to force a login name, in which cause
+.I uucico
+will only prompt for a password.
.TP 5
-.B \-p port
-Specify a port to call out on or to listen to. In slave mode, this
-implies
-.B \-e.
+.B \-p port, \-\-port port
+Specify a port to call out on or to listen to.
.TP 5
-.B \-e
+.B \-e, \-\-loop
Enter endless loop of login/password prompts and slave mode daemon
execution. The program will not stop by itself; you must use
.I kill
(1) to shut it down.
.TP 5
-.B \-w
+.B \-w, \-\-wait
After calling out (to a particular system when
-.B \-s
+.B \-s,
+.B \-\-system,
or
.B \-S
-is specified, or to all systems which have work when
+is specifed, or to all systems which have work when just
.B \-r1
-is specified), begin an endless loop as with
-.B \-e.
+or
+.B \-\-master
+is specifed), begin an endless loop as with
+.B \-\-loop.
.TP 5
-.B \-q
+.B \-q, \-\-nouuxqt
Do not start the
.I uuxqt
(8) daemon when finished.
.TP 5
-.B \-c
+.B \-c, \-\-quiet
If no calls are permitted at this time, then don't make the call, but
also do not put an error message in the log file and do not update the
system status (as reported by
.I uustat
(1)). This can be convenient for automated polling scripts, which may
want to simply attempt to call every system rather than worry about
-which particular systems may be called at the moment.
+which particular systems may be called at the moment. This option
+also suppresses the log message indicating that there is no work to be
+done.
.TP 5
-.B \-D
+.B \-C, \-\-ifwork
+Only call the system named by
+.B \-s,
+.B \-\-system
+or
+.B \-S
+if there is work for that system.
+.TP 5
+.B \-D, \-\-nodetach
Do not detach from the controlling terminal. Normally
.I uucico
detaches from the terminal before each call out to another system and
@@ -170,29 +214,57 @@ before invoking
.I uuxqt.
This option prevents this.
.TP 5
-.B \-x type, \-X type
+.B \-u name, \-\-login name
+Set the login name to use instead of that of the invoking user. This
+option may only be used by the UUCP administrator or the superuser.
+If used with
+.B \-\-prompt,
+this will cause
+.I uucico
+to prompt only for the password, not the login name.
+.TP 5
+.B \-z, \-\-try-next
+If a call fails after the remote system is reached, try the next
+alternate rather than simply exiting.
+.TP 5
+.B \-i type, \-\-stdin type
+Set the type of port to use when using standard input. The only
+support port type is TLI, and this is only available on machines which
+support the TLI networking interface. Specifying
+.B \-iTLI
+causes
+.I uucico
+to use TLI calls to perform I/O.
+.TP 5
+.B \-x type, \-X type, \-\-debug type
Turn on particular debugging types. The following types are
recognized: abnormal, chat, handshake, uucp-proto, proto, port,
config, spooldir, execute, incoming, outgoing.
Multiple types may be given, separated by commas, and the
-.B \-x
+.B \-\-debug
option may appear multiple times. A number may also be given, which
will turn on that many types from the foregoing list; for example,
-.B \-x 2
+.B \-\-debug 2
is equivalent to
-.B \-x abnormal,chat.
+.B \-\-debug abnormal,chat.
The debugging output is sent to the debugging file, usually one of
/usr/spool/uucp/Debug, /usr/spool/uucp/DEBUG, or
/usr/spool/uucp/.Admin/audit.local.
.TP 5
-.B \-I file
+.B \-I file, \-\-config file
Set configuration file to use. This option may not be available,
depending upon how
.I uucico
was compiled.
.TP 5
+.B \-v, \-\-version
+Report version information and exit.
+.TP 5
+.B \-\-help
+Print a help message and exit.
+.TP 5
.B \-u login
This option is ignored. It is only included because some versions of
uucpd invoke
@@ -222,4 +294,4 @@ Debugging file.
kill(1), uucp(1), uux(1), uustat(1), uuxqt(8)
.SH AUTHOR
Ian Lance Taylor
-(ian@airs.com or uunet!airs!ian)
+<ian@airs.com>
diff --git a/gnu/libexec/uucp/uucico/uucico.c b/gnu/libexec/uucp/uucico/uucico.c
index 01717c4bcf4f..29a42573e859 100644
--- a/gnu/libexec/uucp/uucico/uucico.c
+++ b/gnu/libexec/uucp/uucico/uucico.c
@@ -1,7 +1,7 @@
/* uucico.c
This is the main UUCP communication program.
- Copyright (C) 1991, 1992 Ian Lance Taylor
+ Copyright (C) 1991, 1992, 1993, 1994 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char uucico_rcsid[] = "$Id: uucico.c,v 1.1 1993/08/05 18:27:24 conklin Exp $";
+const char uucico_rcsid[] = "$Id: uucico.c,v 1.3 1994/05/25 20:14:52 ache Exp $";
#endif
#include <ctype.h>
@@ -45,10 +45,21 @@ const char uucico_rcsid[] = "$Id: uucico.c,v 1.1 1993/08/05 18:27:24 conklin Exp
#include "prot.h"
#include "trans.h"
#include "system.h"
-
-/* The program name. */
-char abProgram[] = "uucico";
+#if HAVE_ENCRYPTED_PASSWORDS
+#ifndef crypt
+extern char *crypt ();
+#endif
+#endif
+
+/* Coherent already had a different meaning for the -c option. What a
+ pain. */
+#ifdef __COHERENT__
+#define COHERENT_C_OPTION 1
+#else
+#define COHERENT_C_OPTION 0
+#endif
+
/* Define the known protocols. */
#define TCP_PROTO \
@@ -58,30 +69,33 @@ char abProgram[] = "uucico";
static const struct sprotocol asProtocols[] =
{
- { 't', TCP_PROTO, 1,
+ { 't', TCP_PROTO, 1, TRUE,
asTproto_params, ftstart, ftshutdown, ftsendcmd, ztgetspace,
ftsenddata, ftwait, ftfile },
- { 'e', TCP_PROTO, 1,
+ { 'e', TCP_PROTO, 1, TRUE,
asEproto_params, festart, feshutdown, fesendcmd, zegetspace,
fesenddata, fewait, fefile },
- { 'i', UUCONF_RELIABLE_EIGHT, 7,
+ { 'i', UUCONF_RELIABLE_EIGHT, 7, TRUE,
asIproto_params, fistart, fishutdown, fisendcmd, zigetspace,
fisenddata, fiwait, NULL },
- { 'a', UUCONF_RELIABLE_EIGHT, 1,
+ { 'a', UUCONF_RELIABLE_EIGHT, 1, TRUE,
asZproto_params, fzstart, fzshutdown, fzsendcmd, zzgetspace,
fzsenddata, fzwait, fzfile },
- { 'g', UUCONF_RELIABLE_EIGHT, 1,
+ { 'g', UUCONF_RELIABLE_EIGHT, 1, TRUE,
asGproto_params, fgstart, fgshutdown, fgsendcmd, zggetspace,
fgsenddata, fgwait, NULL },
- { 'G', UUCONF_RELIABLE_EIGHT, 1,
+ { 'G', UUCONF_RELIABLE_EIGHT, 1, TRUE,
asGproto_params, fbiggstart, fgshutdown, fgsendcmd, zggetspace,
fgsenddata, fgwait, NULL },
- { 'j', UUCONF_RELIABLE_EIGHT, 7,
+ { 'j', UUCONF_RELIABLE_EIGHT, 7, TRUE,
asIproto_params, fjstart, fjshutdown, fisendcmd, zigetspace,
fisenddata, fiwait, NULL },
- { 'f', UUCONF_RELIABLE_RELIABLE, 1,
+ { 'f', UUCONF_RELIABLE_RELIABLE, 1, FALSE,
asFproto_params, ffstart, ffshutdown, ffsendcmd, zfgetspace,
ffsenddata, ffwait, fffile },
+ { 'v', UUCONF_RELIABLE_EIGHT, 1, TRUE,
+ asGproto_params, fvstart, fgshutdown, fgsendcmd, zggetspace,
+ fgsenddata, fgwait, NULL }
};
#define CPROTOCOLS (sizeof asProtocols / sizeof asProtocols[0])
@@ -112,12 +126,13 @@ struct spass
/* Local functions. */
static void uusage P((void));
+static void uhelp P((void));
static void uabort P((void));
-static boolean fcall P((pointer puuconf,
+static boolean fcall P((pointer puuconf, const char *zconfig, boolean fuuxqt,
const struct uuconf_system *qsys,
struct uuconf_port *qport, boolean fifwork,
boolean fforce, boolean fdetach,
- boolean ftimewarn));
+ boolean fquiet, boolean ftrynext));
static boolean fconn_call P((struct sdaemon *qdaemon,
struct uuconf_port *qport,
struct sstatus *qstat, int cretry,
@@ -127,11 +142,19 @@ static boolean fdo_call P((struct sdaemon *qdaemon,
const struct uuconf_dialer *qdialer,
boolean *pfcalled, enum tstatus_type *pterr));
static int iuport_lock P((struct uuconf_port *qport, pointer pinfo));
-static boolean flogin_prompt P((pointer puuconf,
- struct sconnection *qconn));
-static boolean faccept_call P((pointer puuconf, const char *zlogin,
+static boolean flogin_prompt P((pointer puuconf, const char *zconfig,
+ boolean fuuxqt, struct sconnection *qconn,
+ const char *zlogin));
+static int icallin_cmp P((int iwhich, pointer pinfo, const char *zfile));
+static boolean faccept_call P((pointer puuconf, const char *zconfig,
+ boolean fuuxqt, const char *zlogin,
struct sconnection *qconn,
const char **pzsystem));
+static void uaccept_call_cleanup P((pointer puuconf,
+ struct uuconf_system *qfreesys,
+ struct uuconf_port *qport,
+ struct uuconf_port *qfreeport,
+ char *zloc));
static void uapply_proto_params P((pointer puuconf, int bproto,
struct uuconf_cmdtab *qcmds,
struct uuconf_proto_param *pas));
@@ -142,21 +165,47 @@ static char *zget_uucp_cmd P((struct sconnection *qconn,
static char *zget_typed_line P((struct sconnection *qconn));
/* Long getopt options. */
-static const struct option asLongopts[] = { { NULL, 0, NULL, 0 } };
+static const struct option asLongopts[] =
+{
+ { "quiet", no_argument, NULL, 2 },
+ { "ifwork", no_argument, NULL, 'C' },
+ { "nodetach", no_argument, NULL, 'D' },
+ { "loop", no_argument, NULL, 'e' },
+ { "force", no_argument, NULL, 'f'},
+ { "stdin", required_argument, NULL, 'i' },
+ { "prompt", no_argument, NULL, 'l' },
+ { "port", required_argument, NULL, 'p' },
+ { "nouuxqt", no_argument, NULL, 'q' },
+ { "master", no_argument, NULL, 3 },
+ { "slave", no_argument, NULL, 4 },
+ { "system", required_argument, NULL, 's' },
+ { "login", required_argument, NULL, 'u' },
+ { "wait", no_argument, NULL, 'w' },
+ { "try-next", no_argument, NULL, 'z' },
+ { "config", required_argument, NULL, 'I' },
+ { "debug", required_argument, NULL, 'x' },
+ { "version", no_argument, NULL, 'v' },
+ { "help", no_argument, NULL, 1 },
+ { NULL, 0, NULL, 0 }
+};
int
main (argc, argv)
int argc;
char **argv;
{
- /* -c: Whether to warn if a call is attempted at a bad time. */
- boolean ftimewarn = TRUE;
+ /* -c: Whether to be quiet. */
+ boolean fquiet = FALSE;
+ /* -C: Only call the system if there is work. */
+ boolean fifwork = FALSE;
/* -D: don't detach from controlling terminal. */
boolean fdetach = TRUE;
/* -e: Whether to do an endless loop of accepting calls. */
boolean fendless = FALSE;
/* -f: Whether to force a call despite status of previous call. */
boolean fforce = FALSE;
+ /* -i type: type of port to use for stdin. */
+ enum uuconf_porttype tstdintype = UUCONF_PORTTYPE_STDIN;
/* -I file: configuration file name. */
const char *zconfig = NULL;
/* -l: Whether to give a single login prompt. */
@@ -172,8 +221,13 @@ main (argc, argv)
boolean fmaster = FALSE;
/* -s,-S system: system to call. */
const char *zsystem = NULL;
+ /* -u: Login name to use. */
+ const char *zlogin = NULL;
/* -w: Whether to wait for a call after doing one. */
boolean fwait = FALSE;
+ /* -z: Try next alternate if call fails. */
+ boolean ftrynext = FALSE;
+ const char *zopts;
int iopt;
struct uuconf_port *qport;
struct uuconf_port sport;
@@ -184,15 +238,40 @@ main (argc, argv)
int iholddebug;
#endif
- while ((iopt = getopt_long (argc, argv,
- "cDefI:lp:qr:s:S:u:x:X:w",
+ zProgram = argv[0];
+
+ /* When uucico is invoked by login, the first character of the
+ program will be a dash. We don't want that. */
+ if (*zProgram == '-')
+ ++zProgram;
+
+#if COHERENT_C_OPTION
+ zopts = "c:CDefi:I:lp:qr:s:S:u:x:X:vwz";
+#else
+ zopts = "cCDefi:I:lp:qr:s:S:u:x:X:vwz";
+#endif
+
+ while ((iopt = getopt_long (argc, argv, zopts,
asLongopts, (int *) NULL)) != EOF)
{
+#if COHERENT_C_OPTION
+ if (iopt == 'c')
+ {
+ iopt = 's';
+ fifwork = TRUE;
+ }
+#endif
switch (iopt)
{
+ case 2:
case 'c':
- /* Don't warn if a call is attempted at a bad time. */
- ftimewarn = FALSE;
+ /* Don't warn if a call is attempted at a bad time, and
+ don't print the "No work" message. */
+ fquiet = TRUE;
+ break;
+
+ case 'C':
+ fifwork = TRUE;
break;
case 'D':
@@ -211,10 +290,23 @@ main (argc, argv)
fforce = TRUE;
break;
- case 'I':
- /* Set configuration file name (default is in sysdep.h). */
- if (fsysdep_other_config (optarg))
- zconfig = optarg;
+ case 'i':
+ /* Type of port to use for standard input. Only TLI is
+ supported here, and only if HAVE_TLI is true. This
+ permits the Network Listener to tell uucico to use TLI
+ I/O calls. */
+ if (strcasecmp (optarg, "tli") != 0)
+ fprintf (stderr, "%s: unsupported port type \"%s\"\n",
+ zProgram, optarg);
+ else
+ {
+#if HAVE_TLI
+ tstdintype = UUCONF_PORTTYPE_TLI;
+#else
+ fprintf (stderr, "%s: not compiled with TLI support\n",
+ zProgram);
+#endif
+ }
break;
case 'l':
@@ -257,31 +349,71 @@ main (argc, argv)
case 'u':
/* Some versions of uucpd invoke uucico with a -u argument
- specifying the login name. I'm told it is safe to ignore
- this value, although perhaps we should use it rather than
- zsysdep_login_name (). */
+ specifying the login name. If invoked by a privileged
+ user, we use it instead of the result of
+ zsysdep_login_name. */
+ if (fsysdep_privileged ())
+ zlogin = optarg;
+ else
+ fprintf (stderr,
+ "%s: ignoring command line login name: not a privileged user\n",
+ zProgram);
+ break;
+
+ case 'w':
+ /* Call out and then wait for a call in */
+ fwait = TRUE;
+ break;
+
+ case 'z':
+ /* Try next alternate if call fails. */
+ ftrynext = TRUE;
+ break;
+
+ case 'I':
+ /* Set configuration file name (default is in sysdep.h). */
+ if (fsysdep_other_config (optarg))
+ zconfig = optarg;
break;
case 'x':
case 'X':
#if DEBUG > 1
- /* Set debugging level */
+ /* Set debugging level. */
iDebug |= idebug_parse (optarg);
#endif
break;
- case 'w':
- /* Call out and then wait for a call in */
- fwait = TRUE;
+ case 'v':
+ /* Print version and exit. */
+ printf ("%s: Taylor UUCP %s, copyright (C) 1991, 1992, 1993, 1994 Ian Lance Taylor\n",
+ zProgram, VERSION);
+ exit (EXIT_SUCCESS);
+ /*NOTREACHED*/
+
+ case 4:
+ /* --slave. */
+ fmaster = FALSE;
+ break;
+
+ case 3:
+ /* --master. */
+ fmaster = TRUE;
break;
+ case 1:
+ /* --help. */
+ uhelp ();
+ exit (EXIT_SUCCESS);
+ /*NOTREACHED*/
+
case 0:
/* Long option found, and flag value set. */
break;
default:
uusage ();
- break;
+ /*NOTREACHED*/
}
}
@@ -290,7 +422,7 @@ main (argc, argv)
if (fwait && zport == NULL)
{
- ulog (LOG_ERROR, "-w requires -e");
+ fprintf (stderr, "%s: -w requires -p", zProgram);
uusage ();
}
@@ -321,7 +453,7 @@ main (argc, argv)
pointer))) NULL,
(pointer) NULL, &sport);
if (iuuconf == UUCONF_NOT_FOUND)
- ulog (LOG_FATAL, "%s: Port not found", zport);
+ ulog (LOG_FATAL, "%s: port not found", zport);
else if (iuuconf != UUCONF_SUCCESS)
ulog_uuconf (LOG_FATAL, puuconf, iuuconf);
qport = &sport;
@@ -384,8 +516,8 @@ main (argc, argv)
else
{
fLocked_system = TRUE;
- fret = fcall (puuconf, &sLocked_system, qport, FALSE,
- fforce, fdetach, ftimewarn);
+ fret = fcall (puuconf, zconfig, fuuxqt, &sLocked_system, qport,
+ fifwork, fforce, fdetach, fquiet, ftrynext);
if (fLocked_system)
{
(void) fsysdep_unlock_system (&sLocked_system);
@@ -468,8 +600,9 @@ main (argc, argv)
else
{
fLocked_system = TRUE;
- if (! fcall (puuconf, &sLocked_system, qport, TRUE,
- fforce, fdetach, ftimewarn))
+ if (! fcall (puuconf, zconfig, fuuxqt, &sLocked_system,
+ qport, TRUE, fforce, fdetach, fquiet,
+ ftrynext))
fret = FALSE;
/* Now ignore any SIGHUP that we got. */
@@ -493,7 +626,7 @@ main (argc, argv)
xfree ((pointer) pznames);
- if (! fdidone)
+ if (! fdidone && ! fquiet)
ulog (LOG_NORMAL, "No work");
}
@@ -520,7 +653,7 @@ main (argc, argv)
fret = TRUE;
zsystem = NULL;
- if (! fconn_init (qport, &sconn))
+ if (! fconn_init (qport, &sconn, tstdintype))
fret = FALSE;
if (qport != NULL)
@@ -531,9 +664,6 @@ main (argc, argv)
if (fdetach
&& qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN)
usysdep_detach ();
-
- /* If a port was given, we loop forever. */
- fendless = TRUE;
}
if (fconn_lock (&sconn, TRUE))
@@ -558,17 +688,14 @@ main (argc, argv)
if (fendless)
{
while (! FGOT_SIGNAL ()
- && flogin_prompt (puuconf, &sconn))
+ && flogin_prompt (puuconf, zconfig, fuuxqt, &sconn,
+ (const char *) NULL))
{
- /* Now ignore any SIGHUP that we got. */
- afSignal[INDEXSIG_SIGHUP] = FALSE;
-
- if (fLocked_system)
- {
- (void) fsysdep_unlock_system (&sLocked_system);
- fLocked_system = FALSE;
- }
- if (! fconn_reset (&sconn))
+ /* Close and reopen the port in between calls. */
+ if (! fconn_close (&sconn, puuconf,
+ (struct uuconf_dialer *) NULL,
+ TRUE)
+ || ! fconn_open (&sconn, (long) 0, (long) 0, TRUE))
break;
}
fret = FALSE;
@@ -576,13 +703,16 @@ main (argc, argv)
else
{
if (flogin)
- fret = flogin_prompt (puuconf, &sconn);
+ fret = flogin_prompt (puuconf, zconfig, fuuxqt, &sconn,
+ zlogin);
else
{
#if DEBUG > 1
iholddebug = iDebug;
#endif
- fret = faccept_call (puuconf, zsysdep_login_name (),
+ if (zlogin == NULL)
+ zlogin = zsysdep_login_name ();
+ fret = faccept_call (puuconf, zconfig, fuuxqt, zlogin,
&sconn, &zsystem);
#if DEBUG > 1
iDebug = iholddebug;
@@ -602,12 +732,6 @@ main (argc, argv)
if (flocked)
(void) fconn_unlock (&sconn);
- if (fLocked_system)
- {
- (void) fsysdep_unlock_system (&sLocked_system);
- fLocked_system = FALSE;
- }
-
uconn_free (&sconn);
}
@@ -622,19 +746,19 @@ main (argc, argv)
if (fuuxqt)
{
- /* Detach from the controlling terminal before starting up uuxqt,
- so that it runs as a true daemon. */
- if (fdetach)
- usysdep_detach ();
- if (zsystem == NULL)
- {
- if (! fsysdep_run ("uuxqt", (const char *) NULL,
- (const char *) NULL))
- fret = FALSE;
- }
- else
+ int irunuuxqt;
+
+ iuuconf = uuconf_runuuxqt (puuconf, &irunuuxqt);
+ if (iuuconf != UUCONF_SUCCESS)
+ ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
+ else if (irunuuxqt == UUCONF_RUNUUXQT_ONCE)
{
- if (! fsysdep_run ("uuxqt", "-s", zsystem))
+ /* Detach from the controlling terminal before starting up uuxqt,
+ so that it runs as a true daemon. */
+ if (fdetach)
+ usysdep_detach ();
+
+ if (! fspawn_uuxqt (FALSE, zsystem, zconfig))
fret = FALSE;
}
}
@@ -645,40 +769,46 @@ main (argc, argv)
return 0;
}
-/* Print out a usage message. */
+/* Print out a usage message and die. */
static void
uusage ()
{
- fprintf (stderr,
- "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n",
+ fprintf (stderr, "Usage: %s [options]\n", zProgram);
+ fprintf (stderr, "Use %s --help for help\n", zProgram);
+ exit (EXIT_FAILURE);
+}
+
+/* Print a help message. */
+
+static void
+uhelp ()
+{
+ printf ("Taylor UUCP %s, copyright (C) 1991, 1992, 1993, 1994 Ian Lance Taylor\n",
VERSION);
- fprintf (stderr,
- "Usage: uucico [options]\n");
- fprintf (stderr,
- " -s,-S system: Call system (-S implies -f)\n");
- fprintf (stderr,
- " -f: Force call despite system status\n");
- fprintf (stderr,
- " -r state: 1 for master, 0 for slave (default)\n");
- fprintf (stderr,
- " -p port: Specify port (implies -e)\n");
- fprintf (stderr,
- " -l: prompt for login name and password\n");
- fprintf (stderr,
- " -e: Endless loop of login prompts and daemon execution\n");
- fprintf (stderr,
- " -w: After calling out, wait for incoming calls\n");
- fprintf (stderr,
- " -q: Don't start uuxqt when done\n");
- fprintf (stderr,
- " -x,-X debug: Set debugging level\n");
+ printf ("Usage: %s [options]\n", zProgram);
+ printf (" -s,-S,--system system: Call system (-S implies -f)\n");
+ printf (" -f,--force: Force call despite system status\n");
+ printf (" -r state: 1 for master, 0 for slave (default)\n");
+ printf (" --master: Act as master\n");
+ printf (" --slave: Act as slave (default)\n");
+ printf (" -p,--port port: Specify port\n");
+ printf (" -l,--prompt: prompt for login name and password\n");
+ printf (" -e,--loop: Endless loop of login prompts and daemon execution\n");
+ printf (" -w,--wait: After calling out, wait for incoming calls\n");
+ printf (" -q,--nouuxqt: Don't start uuxqt when done\n");
+ printf (" -c,--quiet: Don't log bad time or no work warnings\n");
+ printf (" -C,--ifwork: Only call named system if there is work\n");
+ printf (" -D,--nodetach: Don't detach from controlling terminal\n");
+ printf (" -u,--login: Set login name (privileged users only)\n");
+ printf (" -i,--stdin type: Type of standard input (only TLI supported)\n");
+ printf (" -z,--try-next: If a call fails, try the next alternate\n");
+ printf (" -x,-X,--debug debug: Set debugging level\n");
#if HAVE_TAYLOR_CONFIG
- fprintf (stderr,
- " -I file: Set configuration file to use\n");
+ printf (" -I,--config file: Set configuration file to use\n");
#endif /* HAVE_TAYLOR_CONFIG */
-
- exit (EXIT_FAILURE);
+ printf (" -v,--version: Print version and exit\n");
+ printf (" --help: Print help and exit\n");
}
/* This function is called when a LOG_FATAL error occurs. */
@@ -713,28 +843,36 @@ uabort ()
usysdep_exit (FALSE);
}
+/* The number of seconds in one day. We must cast to long for this
+ to be calculated correctly on a machine with 16 bit ints. */
+#define SECS_PER_DAY ((long) 24 * (long) 60 * (long) 60)
+
/* Call another system, trying all the possible sets of calling
instructions. The qsys argument is the system to call. The qport
argument is the port to use, and may be NULL. If the fifwork
argument is TRUE, the call is only placed if there is work to be
done. If the fforce argument is TRUE, a call is forced even if not
- enough time has passed since the last failed call. If the
- ftimewarn argument is TRUE (the normal case), then a warning is
- given if calls are not permitted at this time. */
+ enough time has passed since the last failed call. If the fquiet
+ argument is FALSE (the normal case), then a warning is given if
+ calls are not permitted at this time. */
static boolean
-fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
+fcall (puuconf, zconfig, fuuxqt, qorigsys, qport, fifwork, fforce, fdetach,
+ fquiet, ftrynext)
pointer puuconf;
+ const char *zconfig;
+ boolean fuuxqt;
const struct uuconf_system *qorigsys;
struct uuconf_port *qport;
boolean fifwork;
boolean fforce;
boolean fdetach;
- boolean ftimewarn;
+ boolean fquiet;
+ boolean ftrynext;
{
struct sstatus sstat;
long inow;
- boolean fbadtime, fnevertime;
+ boolean fbadtime, fnevertime, ffoundwork;
const struct uuconf_system *qsys;
if (! fsysdep_get_status (qorigsys, &sstat, (boolean *) NULL))
@@ -744,21 +882,24 @@ fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
that we haven't exceeded the maximum number of retries. Even if
we are over the limit on retries, we permit a call to be made if
24 hours have passed. This 24 hour limit is still controlled by
- the retry time. */
+ the retry time. We ignore times in the future, presumably the
+ result of some sort of error. */
inow = ixsysdep_time ((long *) NULL);
if (! fforce)
{
if (qorigsys->uuconf_cmax_retries > 0
&& sstat.cretries >= qorigsys->uuconf_cmax_retries
- && sstat.ilast + 24 * 60 * 60 < inow)
+ && sstat.ilast <= inow
+ && sstat.ilast + SECS_PER_DAY > inow)
{
ulog (LOG_ERROR, "Too many retries");
return FALSE;
}
- if (sstat.ttype == STATUS_COMPLETE
- ? sstat.ilast + qorigsys->uuconf_csuccess_wait > inow
- : sstat.ilast + sstat.cwait > inow)
+ if ((sstat.ttype == STATUS_COMPLETE
+ ? sstat.ilast + qorigsys->uuconf_csuccess_wait > inow
+ : sstat.ilast + sstat.cwait > inow)
+ && sstat.ilast <= inow)
{
ulog (LOG_NORMAL, "Retry time not reached");
return FALSE;
@@ -766,25 +907,21 @@ fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
}
sDaemon.puuconf = puuconf;
- sDaemon.qsys = NULL;
- sDaemon.zlocalname = NULL;
- sDaemon.qconn = NULL;
- sDaemon.qproto = NULL;
- sDaemon.clocal_size = -1;
- sDaemon.cremote_size = -1;
- sDaemon.cmax_ever = -2;
- sDaemon.cmax_receive = -1;
- sDaemon.ifeatures = 0;
- sDaemon.frequest_hangup = FALSE;
- sDaemon.fhangup_requested = FALSE;
- sDaemon.fhangup = FALSE;
- sDaemon.fmaster = TRUE;
- sDaemon.fcaller = TRUE;
- sDaemon.ireliable = 0;
- sDaemon.bgrade = '\0';
+ sDaemon.zconfig = zconfig;
+ if (! fuuxqt)
+ sDaemon.irunuuxqt = UUCONF_RUNUUXQT_NEVER;
+ else
+ {
+ int iuuconf;
+
+ iuuconf = uuconf_runuuxqt (puuconf, &sDaemon.irunuuxqt);
+ if (iuuconf != UUCONF_SUCCESS)
+ ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
+ }
fbadtime = TRUE;
fnevertime = TRUE;
+ ffoundwork = FALSE;
for (qsys = qorigsys; qsys != NULL; qsys = qsys->uuconf_qalternate)
{
@@ -804,7 +941,28 @@ fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
&cretry))
continue;
+ fbadtime = FALSE;
+
sDaemon.qsys = qsys;
+ sDaemon.zlocalname = NULL;
+ sDaemon.qconn = NULL;
+ sDaemon.qproto = NULL;
+ sDaemon.cchans = 1;
+ sDaemon.clocal_size = -1;
+ sDaemon.cremote_size = -1;
+ sDaemon.cmax_ever = -2;
+ sDaemon.cmax_receive = -1;
+ sDaemon.csent = 0;
+ sDaemon.creceived = 0;
+ sDaemon.cxfiles_received = 0;
+ sDaemon.ifeatures = 0;
+ sDaemon.frequest_hangup = FALSE;
+ sDaemon.fhangup_requested = FALSE;
+ sDaemon.fhangup = FALSE;
+ sDaemon.fmaster = TRUE;
+ sDaemon.fcaller = TRUE;
+ sDaemon.ireliable = 0;
+ sDaemon.bgrade = '\0';
/* Queue up any work there is to do. */
if (! fqueue (&sDaemon, &fany))
@@ -820,7 +978,7 @@ fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
continue;
}
- fbadtime = FALSE;
+ ffoundwork = TRUE;
fret = fconn_call (&sDaemon, qport, &sstat, cretry, &fcalled);
@@ -828,7 +986,7 @@ fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
if (fret)
return TRUE;
- if (fcalled)
+ if (fcalled && ! ftrynext)
return FALSE;
/* Now we have to dump that port so that we can aquire a new
@@ -845,9 +1003,16 @@ fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
}
}
- if (fbadtime && ftimewarn)
+ /* We only get here if no call succeeded. If fbadtime is TRUE it
+ was the wrong time for all the alternates. Otherwise, if
+ ffoundwork is FALSE there was no work for any of the alternates.
+ Otherwise, we attempted a call and fconn_call logged an error
+ message. */
+
+ if (fbadtime)
{
- ulog (LOG_NORMAL, "Wrong time to call");
+ if (! fquiet)
+ ulog (LOG_NORMAL, "Wrong time to call");
/* Update the status, unless the system can never be called. If
the system can never be called, there is little point to
@@ -862,6 +1027,12 @@ fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn)
(void) fsysdep_set_status (qorigsys, &sstat);
}
}
+ else if (! ffoundwork)
+ {
+ if (! fquiet)
+ ulog (LOG_NORMAL, "No work");
+ return TRUE;
+ }
return FALSE;
}
@@ -905,7 +1076,7 @@ fconn_call (qdaemon, qport, qstat, cretry, pfcalled)
qport = qsys->uuconf_qport;
if (qport != NULL)
{
- if (! fconn_init (qport, &sconn))
+ if (! fconn_init (qport, &sconn, UUCONF_PORTTYPE_UNKNOWN))
return FALSE;
if (! fconn_lock (&sconn, FALSE))
{
@@ -972,6 +1143,7 @@ fconn_call (qdaemon, qport, qstat, cretry, pfcalled)
if (! fconn_dial (&sconn, puuconf, qsys, qsys->uuconf_zphone,
&sdialer, &tdialer))
{
+ tdialer = DIALERFOUND_FALSE;
terr = STATUS_DIAL_FAILED;
fret = FALSE;
}
@@ -1068,7 +1240,8 @@ fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
if (strncmp (zstr, "Shere", 5) != 0)
{
- ulog (LOG_ERROR, "Bad initialization string");
+ ulog (LOG_ERROR, "Bad startup string (expected \"Shere\" got \"%s\")",
+ zstr);
ubuffree (zstr);
return FALSE;
}
@@ -1218,7 +1391,7 @@ fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
if (zstr[0] != 'R')
{
- ulog (LOG_ERROR, "Bad reponse to handshake string (%s)",
+ ulog (LOG_ERROR, "Bad response to handshake string (%s)",
zstr);
ubuffree (zstr);
return FALSE;
@@ -1376,6 +1549,14 @@ fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
qdaemon->qproto = &asProtocols[i];
+ /* If we are using a half-duplex line, act as though we have only
+ a single channel; otherwise we might start a send and a receive
+ at the same time. */
+ if ((qdaemon->ireliable & UUCONF_RELIABLE_FULLDUPLEX) == 0)
+ qdaemon->cchans = 1;
+ else
+ qdaemon->cchans = asProtocols[i].cchans;
+
sprintf (ab, "U%c", qdaemon->qproto->bname);
if (! fsend_uucp_cmd (qconn, ab))
return FALSE;
@@ -1449,8 +1630,12 @@ fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
iend_time = ixsysdep_time ((long *) NULL);
- ulog (LOG_NORMAL, "Call complete (%ld seconds)",
- iend_time - istart_time);
+ ulog (LOG_NORMAL, "Call complete (%ld seconds %ld bytes %ld bps)",
+ iend_time - istart_time,
+ qdaemon->csent + qdaemon->creceived,
+ (iend_time != istart_time
+ ? (qdaemon->csent + qdaemon->creceived) / (iend_time - istart_time)
+ : 0));
if (fret)
{
@@ -1459,6 +1644,11 @@ fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr)
(void) fsysdep_set_status (qsys, qstat);
}
+ if (qdaemon->irunuuxqt == UUCONF_RUNUUXQT_PERCALL
+ || (qdaemon->irunuuxqt > 0 && qdaemon->cxfiles_received > 0))
+ (void) fspawn_uuxqt (TRUE, qdaemon->qsys->uuconf_zname,
+ qdaemon->zconfig);
+
return fret;
}
}
@@ -1477,7 +1667,7 @@ iuport_lock (qport, pinfo)
q->fmatched = TRUE;
- if (! fconn_init (qport, q->qconn))
+ if (! fconn_init (qport, q->qconn, UUCONF_PORTTYPE_UNKNOWN))
return UUCONF_NOT_FOUND;
else if (! fconn_lock (q->qconn, FALSE))
{
@@ -1491,31 +1681,49 @@ iuport_lock (qport, pinfo)
}
}
+/* The information structure used for the uuconf_callin comparison
+ function. */
+
+struct scallin_info
+{
+ const char *zuser;
+ const char *zpass;
+};
+
/* Prompt for a login name and a password, and run as the slave. */
static boolean
-flogin_prompt (puuconf, qconn)
+flogin_prompt (puuconf, zconfig, fuuxqt, qconn, zlogin)
pointer puuconf;
+ const char *zconfig;
+ boolean fuuxqt;
struct sconnection *qconn;
+ const char *zlogin;
{
char *zuser, *zpass;
boolean fret;
int iuuconf;
+ struct scallin_info s;
DEBUG_MESSAGE0 (DEBUG_HANDSHAKE, "flogin_prompt: Waiting for login");
zuser = NULL;
- do
+ if (zlogin == NULL)
{
- ubuffree (zuser);
- if (! fconn_write (qconn, "login: ", sizeof "login: " - 1))
- return FALSE;
- zuser = zget_typed_line (qconn);
- }
- while (zuser != NULL && *zuser == '\0');
+ do
+ {
+ ubuffree (zuser);
+ if (! fconn_write (qconn, "login: ", sizeof "login: " - 1))
+ return FALSE;
+ zuser = zget_typed_line (qconn);
+ }
+ while (zuser != NULL && *zuser == '\0');
- if (zuser == NULL)
- return TRUE;
+ if (zuser == NULL)
+ return TRUE;
+
+ zlogin = zuser;
+ }
if (! fconn_write (qconn, "Password:", sizeof "Password:" - 1))
{
@@ -1532,8 +1740,12 @@ flogin_prompt (puuconf, qconn)
fret = TRUE;
- iuuconf = uuconf_callin (puuconf, zuser, zpass);
+ s.zuser = zlogin;
+ s.zpass = zpass;
+ iuuconf = uuconf_callin (puuconf, icallin_cmp, &s);
+
ubuffree (zpass);
+
if (iuuconf == UUCONF_NOT_FOUND)
ulog (LOG_ERROR, "Bad login");
else if (iuuconf != UUCONF_SUCCESS)
@@ -1553,7 +1765,8 @@ flogin_prompt (puuconf, qconn)
#if DEBUG > 1
iholddebug = iDebug;
#endif
- (void) faccept_call (puuconf, zuser, qconn, (const char **) NULL);
+ (void) faccept_call (puuconf, zconfig, fuuxqt, zlogin, qconn,
+ (const char **) NULL);
#if DEBUG > 1
iDebug = iholddebug;
#endif
@@ -1564,12 +1777,43 @@ flogin_prompt (puuconf, qconn)
return fret;
}
+/* The comparison function which we pass to uuconf_callin. This
+ expands escape sequences in the login name, and either encrypts or
+ expands escape sequences in the password. */
+
+static int
+icallin_cmp (iwhich, pinfo, zfile)
+ int iwhich;
+ pointer pinfo;
+ const char *zfile;
+{
+ struct scallin_info *qinfo = (struct scallin_info *) pinfo;
+ char *zcopy;
+ int icmp;
+
+#if HAVE_ENCRYPTED_PASSWORDS
+ if (iwhich != 0)
+ return strcmp (crypt (qinfo->zpass, zfile), zfile) == 0;
+#endif
+
+ zcopy = zbufcpy (zfile);
+ (void) cescape (zcopy);
+ if (iwhich == 0)
+ icmp = strcmp (qinfo->zuser, zcopy);
+ else
+ icmp = strcmp (qinfo->zpass, zcopy);
+ ubuffree (zcopy);
+ return icmp == 0;
+}
+
/* Accept a call from a remote system. If pqsys is not NULL, *pqsys
will be set to the system that called in if known. */
static boolean
-faccept_call (puuconf, zlogin, qconn, pzsystem)
+faccept_call (puuconf, zconfig, fuuxqt, zlogin, qconn, pzsystem)
pointer puuconf;
+ const char *zconfig;
+ boolean fuuxqt;
const char *zlogin;
struct sconnection *qconn;
const char **pzsystem;
@@ -1635,6 +1879,9 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
else if (iuuconf != UUCONF_SUCCESS)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ (struct uuconf_port *) NULL,
+ &sport, (char *) NULL);
return FALSE;
}
else
@@ -1669,14 +1916,27 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
}
sDaemon.puuconf = puuconf;
+ sDaemon.zconfig = zconfig;
+ if (! fuuxqt)
+ sDaemon.irunuuxqt = UUCONF_RUNUUXQT_NEVER;
+ else
+ {
+ iuuconf = uuconf_runuuxqt (puuconf, &sDaemon.irunuuxqt);
+ if (iuuconf != UUCONF_SUCCESS)
+ ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
+ }
sDaemon.qsys = NULL;
sDaemon.zlocalname = NULL;
sDaemon.qconn = qconn;
sDaemon.qproto = NULL;
+ sDaemon.cchans = 1;
sDaemon.clocal_size = -1;
sDaemon.cremote_size = -1;
sDaemon.cmax_ever = -2;
sDaemon.cmax_receive = -1;
+ sDaemon.csent = 0;
+ sDaemon.creceived = 0;
+ sDaemon.cxfiles_received = 0;
sDaemon.ifeatures = 0;
sDaemon.frequest_hangup = FALSE;
sDaemon.fhangup_requested = FALSE;
@@ -1695,11 +1955,17 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
{
sDaemon.zlocalname = zsysdep_localname ();
if (sDaemon.zlocalname == NULL)
- return FALSE;
+ {
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, (char *) NULL);
+ return FALSE;
+ }
}
else
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, (char *) NULL);
return FALSE;
}
@@ -1709,16 +1975,26 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
fret = fsend_uucp_cmd (qconn, zsend);
ubuffree (zsend);
if (! fret)
- return FALSE;
+ {
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, zloc);
+ return FALSE;
+ }
zstr = zget_uucp_cmd (qconn, TRUE);
if (zstr == NULL)
- return FALSE;
+ {
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, zloc);
+ return FALSE;
+ }
if (zstr[0] != 'S')
{
ulog (LOG_ERROR, "Bad introduction string");
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, zloc);
return FALSE;
}
@@ -1740,6 +2016,8 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
xfree ((pointer) zscript);
(void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, zloc);
return FALSE;
}
xfree ((pointer) zscript);
@@ -1748,6 +2026,8 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, zloc);
return FALSE;
}
@@ -1756,6 +2036,8 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
(void) fsend_uucp_cmd (qconn, "RYou are unknown to me");
ulog (LOG_ERROR, "Call from unknown system %s", zstr + 1);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, zloc);
return FALSE;
}
}
@@ -1763,6 +2045,8 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, (struct uuconf_system *) NULL,
+ qport, &sport, zloc);
return FALSE;
}
@@ -1791,6 +2075,7 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
{
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
}
@@ -1801,6 +2086,7 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
ulog (LOG_ERROR, "System %s used wrong login name %s",
zstr + 1, zlogin);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
@@ -1834,15 +2120,25 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
ubuffree (zsysdep_spool_commands (qsys, UUCONF_GRADE_HIGH, 0,
(const struct scmd *) NULL));
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return TRUE;
}
/* We only permit one call at a time from a remote system. Lock it. */
if (! fsysdep_lock_system (qsys))
{
+ if (qsys->uuconf_fsequence)
+ {
+ /* At this point the calling system has already incremented
+ its sequence number, so we increment ours. This will
+ only cause a mismatch if the other system is not what it
+ says it is. */
+ (void) ixsysdep_get_sequence (qsys);
+ }
(void) fsend_uucp_cmd (qconn, "RLCK");
ulog (LOG_ERROR, "System already locked");
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
sLocked_system = *qsys;
@@ -1946,6 +2242,8 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
(void) fsysdep_set_status (qsys, &sstat);
xfree ((pointer) paz);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport,
+ zloc);
return FALSE;
}
fgotseq = TRUE;
@@ -1983,6 +2281,8 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
iwant = (1 << iwant) - 1;
if (qsys->uuconf_zmax_remote_debug != NULL)
iwant &= idebug_parse (qsys->uuconf_zmax_remote_debug);
+ else
+ iwant &= DEBUG_ABNORMAL | DEBUG_CHAT | DEBUG_HANDSHAKE;
if ((iDebug | iwant) != iDebug)
{
iDebug |= iwant;
@@ -2009,6 +2309,7 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
ulog (LOG_ERROR, "No sequence number (call rejected)");
sstat.ttype = STATUS_FAILED;
(void) fsysdep_set_status (qsys, &sstat);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
@@ -2047,6 +2348,7 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
{
sstat.ttype = STATUS_FAILED;
(void) fsysdep_set_status (qsys, &sstat);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
}
@@ -2122,6 +2424,7 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
{
sstat.ttype = STATUS_FAILED;
(void) fsysdep_set_status (qsys, &sstat);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
@@ -2131,15 +2434,17 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
{
sstat.ttype = STATUS_FAILED;
(void) fsysdep_set_status (qsys, &sstat);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
- if (zstr[0] != 'U' || zstr[2] != '\0')
+ if (zstr[0] != 'U')
{
ulog (LOG_ERROR, "Bad protocol response string");
sstat.ttype = STATUS_FAILED;
(void) fsysdep_set_status (qsys, &sstat);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
@@ -2149,6 +2454,7 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
sstat.ttype = STATUS_FAILED;
(void) fsysdep_set_status (qsys, &sstat);
ubuffree (zstr);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
@@ -2163,11 +2469,20 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
ulog (LOG_ERROR, "No supported protocol");
sstat.ttype = STATUS_FAILED;
(void) fsysdep_set_status (qsys, &sstat);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
sDaemon.qproto = &asProtocols[i];
+ /* If we are using a half-duplex line, act as though we have only a
+ single channel; otherwise we might start a send and a receive at
+ the same time. */
+ if ((sDaemon.ireliable & UUCONF_RELIABLE_FULLDUPLEX) == 0)
+ sDaemon.cchans = 1;
+ else
+ sDaemon.cchans = asProtocols[i].cchans;
+
/* Run the chat script for when a call is received. */
if (! fchat (qconn, puuconf, &qsys->uuconf_scalled_chat, qsys,
(const struct uuconf_dialer *) NULL, (const char *) NULL,
@@ -2176,6 +2491,7 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
sstat.ttype = STATUS_FAILED;
sstat.ilast = ixsysdep_time ((long *) NULL);
(void) fsysdep_set_status (qsys, &sstat);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
@@ -2202,15 +2518,16 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
if (qdialer == &sdialer)
(void) uuconf_dialer_free (puuconf, &sdialer);
- /* Get any jobs queued for the system, and turn on the selected
- protocol. */
- if (! fqueue (&sDaemon, (boolean *) NULL)
- || ! (*sDaemon.qproto->pfstart) (&sDaemon, &zlog))
+ /* Turn on the selected protocol and get any jobs queued for the
+ system. */
+ if (! (*sDaemon.qproto->pfstart) (&sDaemon, &zlog)
+ || ! fqueue (&sDaemon, (boolean *) NULL))
{
uclear_queue (&sDaemon);
sstat.ttype = STATUS_FAILED;
sstat.ilast = ixsysdep_time ((long *) NULL);
(void) fsysdep_set_status (qsys, &sstat);
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return FALSE;
}
@@ -2276,8 +2593,12 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
iend_time = ixsysdep_time ((long *) NULL);
- ulog (LOG_NORMAL, "Call complete (%ld seconds)",
- iend_time - istart_time);
+ ulog (LOG_NORMAL, "Call complete (%ld seconds %ld bytes %ld bps)",
+ iend_time - istart_time,
+ sDaemon.csent + sDaemon.creceived,
+ (iend_time != istart_time
+ ? (sDaemon.csent + sDaemon.creceived) / (iend_time - istart_time)
+ : 0));
uclear_queue (&sDaemon);
@@ -2288,14 +2609,38 @@ faccept_call (puuconf, zlogin, qconn, pzsystem)
sstat.ilast = iend_time;
(void) fsysdep_set_status (qsys, &sstat);
- (void) uuconf_system_free (puuconf, &ssys);
- if (qport == &sport)
- (void) uuconf_port_free (puuconf, &sport);
- xfree ((pointer) zloc);
+ if (sDaemon.irunuuxqt == UUCONF_RUNUUXQT_PERCALL
+ || (sDaemon.irunuuxqt > 0 && sDaemon.cxfiles_received > 0))
+ (void) fspawn_uuxqt (TRUE, qsys->uuconf_zname, zconfig);
+
+ uaccept_call_cleanup (puuconf, &ssys, qport, &sport, zloc);
return fret;
}
}
+
+/* Clean up after faccept_call. */
+
+static void
+uaccept_call_cleanup (puuconf, qfreesys, qport, qfreeport, zloc)
+ pointer puuconf;
+ struct uuconf_system *qfreesys;
+ struct uuconf_port *qport;
+ struct uuconf_port *qfreeport;
+ char *zloc;
+{
+ if (fLocked_system)
+ {
+ (void) fsysdep_unlock_system (&sLocked_system);
+ fLocked_system = FALSE;
+ }
+ if (qfreesys != NULL)
+ (void) uuconf_system_free (puuconf, qfreesys);
+ if (qport == qfreeport)
+ (void) uuconf_port_free (puuconf, qfreeport);
+ xfree ((pointer) zloc);
+ ulog_system ((const char *) NULL);
+}
/* Apply protocol parameters, once we know the protocol. */
@@ -2482,7 +2827,8 @@ zget_uucp_cmd (qconn, frequired)
calc += CINCREMENT;
znew = zbufalc (calc);
- memcpy (znew, zalc, cgot);
+ if (cgot > 0)
+ memcpy (znew, zalc, cgot);
ubuffree (zalc);
zalc = znew;
}
@@ -2518,13 +2864,16 @@ zget_uucp_cmd (qconn, frequired)
return NULL;
}
-/* Read a sequence of characters up to a newline or carriage return, and
- return the line without the line terminating character. */
+/* Read a sequence of characters up to a newline or carriage return,
+ and return the line without the line terminating character.
+ Remember whether the last string we returned ended in \r; if it
+ did, ignore a leading \n to account for \r\n pairs. */
static char *
zget_typed_line (qconn)
struct sconnection *qconn;
{
+ static boolean flastcr;
char *zalc;
size_t calc;
size_t cgot;
@@ -2563,11 +2912,15 @@ zget_typed_line (qconn)
}
#endif
ubuffree (zalc);
+ flastcr = FALSE;
return NULL;
}
if (b == -1)
- continue;
+ {
+ flastcr = FALSE;
+ continue;
+ }
#if DEBUG > 1
if (FDEBUGGING (DEBUG_CHAT))
@@ -2586,19 +2939,34 @@ zget_typed_line (qconn)
}
#endif
+ if (b == '\n' && cgot == 0 && flastcr)
+ {
+ /* Ignore \n in \r\n pair. */
+ flastcr = FALSE;
+ continue;
+ }
+
+ flastcr = FALSE;
+
if (cgot >= calc)
{
char *znew;
calc += CINCREMENT;
znew = zbufalc (calc);
- memcpy (znew, zalc, cgot);
+ if (cgot > 0)
+ memcpy (znew, zalc, cgot);
ubuffree (zalc);
zalc = znew;
}
- if (b == '\r' || b == '\n')
+ if (b == '\n')
b = '\0';
+ else if (b == '\r')
+ {
+ flastcr = TRUE;
+ b = '\0';
+ }
zalc[cgot] = (char) b;
++cgot;
@@ -2616,3 +2984,45 @@ zget_typed_line (qconn)
}
}
}
+
+/* Spawn a uuxqt job. This probably belongs in some other file, but I
+ don't have a good place for it. */
+
+boolean
+fspawn_uuxqt (ffork, zsys, zconfig)
+ boolean ffork;
+ const char *zsys;
+ const char *zconfig;
+{
+ char *zsysarg;
+ char *zconfigarg;
+ boolean fret;
+
+ if (zsys == NULL)
+ zsysarg = NULL;
+ else
+ {
+ zsysarg = zbufalc (sizeof "-s" + strlen (zsys));
+ sprintf (zsysarg, "-s%s", zsys);
+ }
+
+ if (zconfig == NULL)
+ zconfigarg = NULL;
+ else
+ {
+ zconfigarg = zbufalc (sizeof "-I" + strlen (zconfig));
+ sprintf (zconfigarg, "-I%s", zconfig);
+ if (zsysarg == NULL)
+ {
+ zsysarg = zconfigarg;
+ zconfigarg = NULL;
+ }
+ }
+
+ fret = fsysdep_run (ffork, "uuxqt", zsysarg, zconfigarg);
+
+ ubuffree (zsysarg);
+ ubuffree (zconfigarg);
+
+ return fret;
+}
diff --git a/gnu/libexec/uucp/uucico/xcmd.c b/gnu/libexec/uucp/uucico/xcmd.c
index cadf6383dff9..a3dc8671d052 100644
--- a/gnu/libexec/uucp/uucico/xcmd.c
+++ b/gnu/libexec/uucp/uucico/xcmd.c
@@ -1,7 +1,7 @@
/* xcmd.c
Routines to handle work requests.
- Copyright (C) 1991, 1992 Ian Lance Taylor
+ Copyright (C) 1991, 1992, 1993 Ian Lance Taylor
This file is part of the Taylor UUCP package.
@@ -20,13 +20,13 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
The author of the program may be contacted at ian@airs.com or
- c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
*/
#include "uucp.h"
#if USE_RCS_ID
-const char xcmd_rcsid[] = "$Id: xcmd.c,v 1.1 1993/08/05 18:27:25 conklin Exp $";
+const char xcmd_rcsid[] = "$Id: xcmd.c,v 1.2 1994/05/07 18:14:04 ache Exp $";
#endif
#include <errno.h>
@@ -77,6 +77,13 @@ flocal_xcmd_request (qtrans, qdaemon)
ulog (LOG_NORMAL, "Requesting work: %s to %s", qtrans->s.zfrom,
qtrans->s.zto);
+
+ qtrans->fcmd = TRUE;
+ qtrans->precfn = flocal_xcmd_await_reply;
+
+ if (! fqueue_receive (qdaemon, qtrans))
+ return FALSE;
+
/* We send the string
X from to user options
We put a dash in front of options. */
@@ -89,16 +96,11 @@ flocal_xcmd_request (qtrans, qdaemon)
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
qtrans->iremote);
ubuffree (zsend);
- if (! fret)
- {
- utransfree (qtrans);
- return FALSE;
- }
- qtrans->fcmd = TRUE;
- qtrans->precfn = flocal_xcmd_await_reply;
+ if (! fret)
+ utransfree (qtrans);
- return fqueue_receive (qdaemon, qtrans);
+ return fret;
}
/* Get a reply to an execution request from the remote system. */
@@ -179,7 +181,8 @@ fremote_xcmd_init (qdaemon, qcmd, iremote)
else
zconst = zexclam + 1;
- zdestfile = zsysdep_local_file (zconst, qsys->uuconf_zpubdir);
+ zdestfile = zsysdep_local_file (zconst, qsys->uuconf_zpubdir,
+ (boolean *) NULL);
if (zdestfile == NULL)
return FALSE;
@@ -252,7 +255,8 @@ fremote_xcmd_init (qdaemon, qcmd, iremote)
/* Now we have to process each source file. The source
specification may or may use wildcards. */
- zfrom = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir);
+ zfrom = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir,
+ (boolean *) NULL);
if (zfrom == NULL)
{
ubuffree (zdestfile);
@@ -341,6 +345,7 @@ fremote_xcmd_init (qdaemon, qcmd, iremote)
char *zjobid;
ssend.bcmd = 'S';
+ ssend.bgrade = BDEFAULT_UUCP_GRADE;
ssend.pseq = NULL;
ssend.zfrom = zfile;
ssend.zto = zdestfile;