summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/buffer.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2002-09-02 05:50:28 +0000
committerpeter <peter@FreeBSD.org>2002-09-02 05:50:28 +0000
commitcf46dfb750863d760d19b9858b0a336b158275da (patch)
tree8440832ece5130fad994f5f3489b01676ab1ca4a /contrib/cvs/src/buffer.c
parent92c0df1bed708821e09e92931a5309cd3abd82fb (diff)
downloadFreeBSD-src-cf46dfb750863d760d19b9858b0a336b158275da.zip
FreeBSD-src-cf46dfb750863d760d19b9858b0a336b158275da.tar.gz
Import cvs-1.11.2 onto vendor branch
Obtained from: http://www.cvshome.org/
Diffstat (limited to 'contrib/cvs/src/buffer.c')
-rw-r--r--contrib/cvs/src/buffer.c167
1 files changed, 148 insertions, 19 deletions
diff --git a/contrib/cvs/src/buffer.c b/contrib/cvs/src/buffer.c
index 8f90545..0c13cde 100644
--- a/contrib/cvs/src/buffer.c
+++ b/contrib/cvs/src/buffer.c
@@ -6,6 +6,12 @@
#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
+#ifdef HAVE_WINSOCK_H
+# include <winsock.h>
+#else
+# include <sys/socket.h>
+#endif
+
/* OS/2 doesn't have EIO. FIXME: this whole notion of turning
a different error into EIO strikes me as pretty dubious. */
#if !defined (EIO)
@@ -28,7 +34,7 @@ buf_initialize (input, output, flush, block, shutdown, memory, closure)
int (*output) PROTO((void *, const char *, int, int *));
int (*flush) PROTO((void *));
int (*block) PROTO((void *, int));
- int (*shutdown) PROTO((void *));
+ int (*shutdown) PROTO((struct buffer *));
void (*memory) PROTO((struct buffer *));
void *closure;
{
@@ -73,7 +79,7 @@ buf_nonio_initialize (memory)
(int (*) PROTO((void *, const char *, int, int *))) NULL,
(int (*) PROTO((void *))) NULL,
(int (*) PROTO((void *, int))) NULL,
- (int (*) PROTO((void *))) NULL,
+ (int (*) PROTO((struct buffer *))) NULL,
memory,
(void *) NULL));
}
@@ -1198,7 +1204,7 @@ buf_shutdown (buf)
struct buffer *buf;
{
if (buf->shutdown)
- return (*buf->shutdown) (buf->closure);
+ return (*buf->shutdown) (buf);
return 0;
}
@@ -1210,22 +1216,35 @@ buf_shutdown (buf)
static int stdio_buffer_input PROTO((void *, char *, int, int, int *));
static int stdio_buffer_output PROTO((void *, const char *, int, int *));
static int stdio_buffer_flush PROTO((void *));
+static int stdio_buffer_shutdown PROTO((struct buffer *buf));
/* Initialize a buffer built on a stdio FILE. */
+struct stdio_buffer_closure
+{
+ FILE *fp;
+ int child_pid;
+};
+
struct buffer *
-stdio_buffer_initialize (fp, input, memory)
+stdio_buffer_initialize (fp, child_pid, input, memory)
FILE *fp;
+ int child_pid;
int input;
void (*memory) PROTO((struct buffer *));
{
+ struct stdio_buffer_closure *bc = malloc (sizeof (*bc));
+
+ bc->fp = fp;
+ bc->child_pid = child_pid;
+
return buf_initialize (input ? stdio_buffer_input : NULL,
input ? NULL : stdio_buffer_output,
input ? NULL : stdio_buffer_flush,
(int (*) PROTO((void *, int))) NULL,
- (int (*) PROTO((void *))) NULL,
+ stdio_buffer_shutdown,
memory,
- (void *) fp);
+ (void *) bc);
}
/* The buffer input function for a buffer built on a stdio FILE. */
@@ -1238,7 +1257,7 @@ stdio_buffer_input (closure, data, need, size, got)
int size;
int *got;
{
- FILE *fp = (FILE *) closure;
+ struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
int nbytes;
/* Since stdio does its own buffering, we don't worry about
@@ -1248,11 +1267,11 @@ stdio_buffer_input (closure, data, need, size, got)
{
int ch;
- ch = getc (fp);
+ ch = getc (bc->fp);
if (ch == EOF)
{
- if (feof (fp))
+ if (feof (bc->fp))
return -1;
else if (errno == 0)
return EIO;
@@ -1265,12 +1284,12 @@ stdio_buffer_input (closure, data, need, size, got)
return 0;
}
- nbytes = fread (data, 1, need, fp);
+ nbytes = fread (data, 1, need, bc->fp);
if (nbytes == 0)
{
*got = 0;
- if (feof (fp))
+ if (feof (bc->fp))
return -1;
else if (errno == 0)
return EIO;
@@ -1292,7 +1311,7 @@ stdio_buffer_output (closure, data, have, wrote)
int have;
int *wrote;
{
- FILE *fp = (FILE *) closure;
+ struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
*wrote = 0;
@@ -1300,7 +1319,7 @@ stdio_buffer_output (closure, data, have, wrote)
{
int nbytes;
- nbytes = fwrite (data, 1, have, fp);
+ nbytes = fwrite (data, 1, have, bc->fp);
if (nbytes != have)
{
@@ -1324,9 +1343,9 @@ static int
stdio_buffer_flush (closure)
void *closure;
{
- FILE *fp = (FILE *) closure;
+ struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
- if (fflush (fp) != 0)
+ if (fflush (bc->fp) != 0)
{
if (errno == 0)
return EIO;
@@ -1337,6 +1356,116 @@ stdio_buffer_flush (closure)
return 0;
}
+
+
+static int
+stdio_buffer_shutdown (buf)
+ struct buffer *buf;
+{
+ struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) buf->closure;
+ struct stat s;
+ int closefp = 1;
+
+ /* Must be a pipe or a socket. What could go wrong? */
+ assert (fstat ( fileno (bc->fp), &s ) != -1);
+
+ /* Flush the buffer if we can */
+ if (buf->flush)
+ {
+ buf_flush (buf, 1);
+ buf->flush = NULL;
+ }
+
+ if (buf->input)
+ {
+ if (! buf_empty_p (buf)
+ || getc (bc->fp) != EOF)
+ {
+# ifdef SERVER_SUPPORT
+ if (server_active)
+ /* FIXME: This should probably be sysloged since it doesn't
+ * have anywhere else to go at this point.
+ */
+ error (0, 0, "dying gasps from client unexpected");
+ else
+#endif
+ error (0, 0, "dying gasps from %s unexpected", current_parsed_root->hostname);
+ }
+ else if (ferror (bc->fp))
+ {
+# ifdef SERVER_SUPPORT
+ if (server_active)
+ /* FIXME: This should probably be sysloged since it doesn't
+ * have anywhere else to go at this point.
+ */
+ error (0, errno, "reading from client");
+ else
+#endif
+ error (0, errno, "reading from %s", current_parsed_root->hostname);
+ }
+
+# ifdef SHUTDOWN_SERVER
+ if (current_parsed_root->method != server_method)
+# endif
+# ifndef NO_SOCKET_TO_FD
+ {
+ /* shutdown() sockets */
+ if (S_ISSOCK(s.st_mode))
+ shutdown ( fileno (bc->fp), 0);
+ }
+# endif /* NO_SOCKET_TO_FD */
+# ifdef START_RSH_WITH_POPEN_RW
+ /* Can't be set with SHUTDOWN_SERVER defined */
+ else if (pclose (bc->fp) == EOF)
+ {
+ error (1, errno, "closing connection to %s",
+ current_parsed_root->hostname);
+ closefp = 0;
+ }
+# endif /* START_RSH_WITH_POPEN_RW */
+
+ buf->input = NULL;
+ }
+ else if (buf->output)
+ {
+# ifdef SHUTDOWN_SERVER
+ /* FIXME: Should have a SHUTDOWN_SERVER_INPUT &
+ * SHUTDOWN_SERVER_OUTPUT
+ */
+ if (current_parsed_root->method == server_method)
+ SHUTDOWN_SERVER ( fileno (bc->fp) );
+ else
+# endif
+# ifndef NO_SOCKET_TO_FD
+ /* shutdown() sockets */
+ if (S_ISSOCK(s.st_mode))
+ shutdown ( fileno (bc->fp), 1);
+# else
+ {
+ /* I'm not sure I like this empty block, but the alternative
+ * is a another nested NO_SOCKET_TO_FD switch above.
+ */
+ }
+# endif /* NO_SOCKET_TO_FD */
+
+ buf->output = NULL;
+ }
+
+ if (closefp && fclose (bc->fp) == EOF)
+ error (1, errno,
+ "closing down connection to %s",
+ current_parsed_root->hostname);
+
+ /* If we were talking to a process, make sure it exited */
+ if (bc->child_pid
+ && waitpid (bc->child_pid, (int *) 0, 0) == -1)
+ error (1, errno, "waiting for process %d", bc->child_pid);
+
+ return 0;
+}
+
+
+
/* Certain types of communication input and output data in packets,
where each packet is translated in some fashion. The packetizing
buffer type supports that, given a buffer which handles lower level
@@ -1398,7 +1527,7 @@ static int packetizing_buffer_input PROTO((void *, char *, int, int, int *));
static int packetizing_buffer_output PROTO((void *, const char *, int, int *));
static int packetizing_buffer_flush PROTO((void *));
static int packetizing_buffer_block PROTO((void *, int));
-static int packetizing_buffer_shutdown PROTO((void *));
+static int packetizing_buffer_shutdown PROTO((struct buffer *));
/* Create a packetizing buffer. */
@@ -1763,10 +1892,10 @@ packetizing_buffer_block (closure, block)
/* Shut down a packetizing buffer. */
static int
-packetizing_buffer_shutdown (closure)
- void *closure;
+packetizing_buffer_shutdown (buf)
+ struct buffer *buf;
{
- struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
+ struct packetizing_buffer *pb = (struct packetizing_buffer *) buf->closure;
return buf_shutdown (pb->buf);
}
OpenPOWER on IntegriCloud