]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/libexec/uucp/common_sources/prot.c
This commit was generated by cvs2svn to compensate for changes in r52744,
[FreeBSD/FreeBSD.git] / gnu / libexec / uucp / common_sources / prot.c
1 /* prot.c
2    Protocol support routines to move commands and data around.
3
4    Copyright (C) 1991, 1992, 1994 Ian Lance Taylor
5
6    This file is part of the Taylor UUCP package.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2 of the
11    License, or (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
22    The author of the program may be contacted at ian@airs.com or
23    c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
24    */
25
26 #include "uucp.h"
27
28 #if USE_RCS_ID
29 const char prot_rcsid[] = "$FreeBSD$";
30 #endif
31
32 #include <errno.h>
33
34 #include "uudefs.h"
35 #include "uuconf.h"
36 #include "system.h"
37 #include "conn.h"
38 #include "prot.h"
39 \f
40 /* Variables visible to the protocol-specific routines.  */
41
42 /* Buffer to hold received data.  */
43 char abPrecbuf[CRECBUFLEN];
44
45 /* Index of start of data in abPrecbuf.  */
46 int iPrecstart;
47
48 /* Index of end of data (first byte not included in data) in abPrecbuf.  */
49 int iPrecend;
50 \f
51 /* We want to output and input at the same time, if supported on this
52    machine.  If we have something to send, we send it all while
53    accepting a large amount of data.  Once we have sent everything we
54    look at whatever we have received.  If data comes in faster than we
55    can send it, we may run out of buffer space.  */
56
57 boolean
58 fsend_data (qconn, zsend, csend, fdoread)
59      struct sconnection *qconn;
60      const char *zsend;
61      size_t csend;
62      boolean fdoread;
63 {
64   if (! fdoread)
65     return fconn_write (qconn, zsend, csend);
66
67   while (csend > 0)
68     {
69       size_t crec, csent;
70
71       if (iPrecend < iPrecstart)
72         crec = iPrecstart - iPrecend - 1;
73       else
74         {
75           crec = CRECBUFLEN - iPrecend;
76           if (iPrecstart == 0)
77             --crec;
78         }
79
80       if (crec == 0)
81         return fconn_write (qconn, zsend, csend);
82
83       csent = csend;
84
85       if (! fconn_io (qconn, zsend, &csent, abPrecbuf + iPrecend, &crec))
86         return FALSE;
87
88       csend -= csent;
89       zsend += csent;
90
91       iPrecend = (iPrecend + crec) % CRECBUFLEN;
92     }
93
94   return TRUE;
95 }
96 \f
97 /* Read data from the other system when we have nothing to send.  The
98    argument cneed is the amount of data the caller wants, and ctimeout
99    is the timeout in seconds.  The function sets *pcrec to the amount
100    of data which was actually received, which may be less than cneed
101    if there isn't enough room in the receive buffer.  If no data is
102    received before the timeout expires, *pcrec will be returned as 0.
103    If an error occurs, the function returns FALSE.  If the freport
104    argument is FALSE, no error should be reported.  */
105
106 boolean
107 freceive_data (qconn, cneed, pcrec, ctimeout, freport)
108      struct sconnection *qconn;
109      size_t cneed;
110      size_t *pcrec;
111      int ctimeout;
112      boolean freport;
113 {
114   /* Set *pcrec to the maximum amount of data we can read.  fconn_read
115      expects *pcrec to be the buffer size, and sets it to the amount
116      actually received.  */
117   if (iPrecend < iPrecstart)
118     *pcrec = iPrecstart - iPrecend - 1;
119   else
120     {
121       *pcrec = CRECBUFLEN - iPrecend;
122       if (iPrecstart == 0)
123         --(*pcrec);
124     }
125
126 #if DEBUG > 0
127   /* If we have no room in the buffer, we're in trouble.  The
128      protocols must be written to ensure that this can't happen.  */
129   if (*pcrec == 0)
130     ulog (LOG_FATAL, "freceive_data: No room in buffer");
131 #endif
132
133   /* If we don't have room for all the data the caller wants, we
134      simply have to expect less.  We'll get the rest later.  */
135   if (*pcrec < cneed)
136     cneed = *pcrec;
137
138   if (! fconn_read (qconn, abPrecbuf + iPrecend, pcrec, cneed, ctimeout,
139                     freport))
140     return FALSE;
141
142   iPrecend = (iPrecend + *pcrec) % CRECBUFLEN;
143
144   return TRUE;
145 }
146 \f
147 /* Read a single character.  Get it out of the receive buffer if it's
148    there, otherwise ask freceive_data for at least one character.
149    This is used because as a protocol is shutting down freceive_data
150    may read ahead and eat characters that should be read outside the
151    protocol routines.  We call freceive_data rather than fconn_read
152    with an argument of 1 so that we can get all the available data in
153    a single system call.  The ctimeout argument is the timeout in
154    seconds; the freport argument is FALSE if no error should be
155    reported.  This returns a character, or -1 on timeout or -2 on
156    error.  */
157
158 int
159 breceive_char (qconn, ctimeout, freport)
160      struct sconnection *qconn;
161      int ctimeout;
162      boolean freport;
163 {
164   char b;
165
166   if (iPrecstart == iPrecend)
167     {
168       size_t crec;
169
170       if (! freceive_data (qconn, sizeof (char), &crec, ctimeout, freport))
171         return -2;
172       if (crec == 0)
173         return -1;
174     }
175
176   b = abPrecbuf[iPrecstart];
177   iPrecstart = (iPrecstart + 1) % CRECBUFLEN;
178   return BUCHAR (b);
179 }
180 \f
181 /* Send mail about a file transfer.  We send to the given mailing
182    address if there is one, otherwise to the user.  */
183
184 boolean
185 fmail_transfer (fsuccess, zuser, zmail, zwhy, zfromfile, zfromsys,
186                 ztofile, ztosys, zsaved)
187      boolean fsuccess;
188      const char *zuser;
189      const char *zmail;
190      const char *zwhy;
191      const char *zfromfile;
192      const char *zfromsys;
193      const char *ztofile;
194      const char *ztosys;
195      const char *zsaved;
196 {
197   const char *zsendto;
198   const char *az[20];
199   int i;
200
201   if (zmail != NULL && *zmail != '\0')
202     zsendto = zmail;
203   else
204     zsendto = zuser;
205
206   i = 0;
207   az[i++] = "The file\n\t";
208   if (zfromsys != NULL)
209     {
210       az[i++] = zfromsys;
211       az[i++] = "!";
212     }
213   az[i++] = zfromfile;
214   if (fsuccess)
215     az[i++] = "\nwas successfully transferred to\n\t";
216   else
217     az[i++] = "\ncould not be transferred to\n\t";
218   if (ztosys != NULL)
219     {
220       az[i++] = ztosys;
221       az[i++] = "!";
222     }
223   az[i++] = ztofile;
224   az[i++] = "\nas requested by\n\t";
225   az[i++] = zuser;
226   if (! fsuccess)
227     {
228       az[i++] = "\nfor the following reason:\n\t";
229       az[i++] = zwhy;
230       az[i++] = "\n";
231     }
232   if (zsaved != NULL)
233     {
234       az[i++] = zsaved;
235       az[i++] = "\n";
236     }
237
238   return fsysdep_mail (zsendto,
239                        fsuccess ? "UUCP succeeded" : "UUCP failed",
240                        i, az);
241 }