summaryrefslogtreecommitdiffstats
path: root/gnu/libexec/uucp/common_sources/prot.c
blob: 54156a4b18d58c012dfc81bc7248b8ac96de4ac6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/* prot.c
   Protocol support routines to move commands and data around.

   Copyright (C) 1991, 1992, 1994 Ian Lance Taylor

   This file is part of the Taylor UUCP package.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

   The author of the program may be contacted at ian@airs.com or
   c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
   */

#include "uucp.h"

#if USE_RCS_ID
const char prot_rcsid[] = "$Id: prot.c,v 1.32 1995/06/21 19:15:07 ian Rel $";
#endif

#include <errno.h>

#include "uudefs.h"
#include "uuconf.h"
#include "system.h"
#include "conn.h"
#include "prot.h"

/* Variables visible to the protocol-specific routines.  */

/* Buffer to hold received data.  */
char abPrecbuf[CRECBUFLEN];

/* Index of start of data in abPrecbuf.  */
int iPrecstart;

/* Index of end of data (first byte not included in data) in abPrecbuf.  */
int iPrecend;

/* We want to output and input at the same time, if supported on this
   machine.  If we have something to send, we send it all while
   accepting a large amount of data.  Once we have sent everything we
   look at whatever we have received.  If data comes in faster than we
   can send it, we may run out of buffer space.  */

boolean
fsend_data (qconn, zsend, csend, fdoread)
     struct sconnection *qconn;
     const char *zsend;
     size_t csend;
     boolean fdoread;
{
  if (! fdoread)
    return fconn_write (qconn, zsend, csend);

  while (csend > 0)
    {
      size_t crec, csent;

      if (iPrecend < iPrecstart)
	crec = iPrecstart - iPrecend - 1;
      else
	{
	  crec = CRECBUFLEN - iPrecend;
	  if (iPrecstart == 0)
	    --crec;
	}

      if (crec == 0)
	return fconn_write (qconn, zsend, csend);

      csent = csend;

      if (! fconn_io (qconn, zsend, &csent, abPrecbuf + iPrecend, &crec))
	return FALSE;

      csend -= csent;
      zsend += csent;

      iPrecend = (iPrecend + crec) % CRECBUFLEN;
    }

  return TRUE;
}

/* Read data from the other system when we have nothing to send.  The
   argument cneed is the amount of data the caller wants, and ctimeout
   is the timeout in seconds.  The function sets *pcrec to the amount
   of data which was actually received, which may be less than cneed
   if there isn't enough room in the receive buffer.  If no data is
   received before the timeout expires, *pcrec will be returned as 0.
   If an error occurs, the function returns FALSE.  If the freport
   argument is FALSE, no error should be reported.  */

boolean
freceive_data (qconn, cneed, pcrec, ctimeout, freport)
     struct sconnection *qconn;
     size_t cneed;
     size_t *pcrec;
     int ctimeout;
     boolean freport;
{
  /* Set *pcrec to the maximum amount of data we can read.  fconn_read
     expects *pcrec to be the buffer size, and sets it to the amount
     actually received.  */
  if (iPrecend < iPrecstart)
    *pcrec = iPrecstart - iPrecend - 1;
  else
    {
      *pcrec = CRECBUFLEN - iPrecend;
      if (iPrecstart == 0)
	--(*pcrec);
    }

#if DEBUG > 0
  /* If we have no room in the buffer, we're in trouble.  The
     protocols must be written to ensure that this can't happen.  */
  if (*pcrec == 0)
    ulog (LOG_FATAL, "freceive_data: No room in buffer");
#endif

  /* If we don't have room for all the data the caller wants, we
     simply have to expect less.  We'll get the rest later.  */
  if (*pcrec < cneed)
    cneed = *pcrec;

  if (! fconn_read (qconn, abPrecbuf + iPrecend, pcrec, cneed, ctimeout,
		    freport))
    return FALSE;

  iPrecend = (iPrecend + *pcrec) % CRECBUFLEN;

  return TRUE;
}

/* Read a single character.  Get it out of the receive buffer if it's
   there, otherwise ask freceive_data for at least one character.
   This is used because as a protocol is shutting down freceive_data
   may read ahead and eat characters that should be read outside the
   protocol routines.  We call freceive_data rather than fconn_read
   with an argument of 1 so that we can get all the available data in
   a single system call.  The ctimeout argument is the timeout in
   seconds; the freport argument is FALSE if no error should be
   reported.  This returns a character, or -1 on timeout or -2 on
   error.  */

int
breceive_char (qconn, ctimeout, freport)
     struct sconnection *qconn;
     int ctimeout;
     boolean freport;
{
  char b;

  if (iPrecstart == iPrecend)
    {
      size_t crec;

      if (! freceive_data (qconn, sizeof (char), &crec, ctimeout, freport))
	return -2;
      if (crec == 0)
	return -1;
    }

  b = abPrecbuf[iPrecstart];
  iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
  return BUCHAR (b);
}

/* Send mail about a file transfer.  We send to the given mailing
   address if there is one, otherwise to the user.  */

boolean
fmail_transfer (fsuccess, zuser, zmail, zwhy, zfromfile, zfromsys,
		ztofile, ztosys, zsaved)
     boolean fsuccess;
     const char *zuser;
     const char *zmail;
     const char *zwhy;
     const char *zfromfile;
     const char *zfromsys;
     const char *ztofile;
     const char *ztosys;
     const char *zsaved;
{
  const char *zsendto;
  const char *az[20];
  int i;

  if (zmail != NULL && *zmail != '\0')
    zsendto = zmail;
  else
    zsendto = zuser;

  i = 0;
  az[i++] = "The file\n\t";
  if (zfromsys != NULL)
    {
      az[i++] = zfromsys;
      az[i++] = "!";
    }
  az[i++] = zfromfile;
  if (fsuccess)
    az[i++] = "\nwas successfully transferred to\n\t";
  else
    az[i++] = "\ncould not be transferred to\n\t";
  if (ztosys != NULL)
    {
      az[i++] = ztosys;
      az[i++] = "!";
    }
  az[i++] = ztofile;
  az[i++] = "\nas requested by\n\t";
  az[i++] = zuser;
  if (! fsuccess)
    {
      az[i++] = "\nfor the following reason:\n\t";
      az[i++] = zwhy;
      az[i++] = "\n";
    }
  if (zsaved != NULL)
    {
      az[i++] = zsaved;
      az[i++] = "\n";
    }

  return fsysdep_mail (zsendto,
		       fsuccess ? "UUCP succeeded" : "UUCP failed",
		       i, az);
}
OpenPOWER on IntegriCloud