/*
 * Read "n" bytes from a descriptor.
 * Use in place of read() when fd is a stream socket
 *
 * Returns the number of total bytes read.
 */

int
readn(fd, ptr, nbytes)
int fd;
char *ptr;
int nbytes;
{
	int nleft, nread;

	nleft = nbytes;
	while (nleft > 0) {
		nread = read(fd, ptr, nleft);
		if (nread < 0)
			return(nread);	/* error, return <0 */
		else if (nread == 0)	/* EOF */
			break;
	
		nleft 	-= nread;
		ptr 	+= nread;
	}
	return(nbytes - nleft);	/* return >= 0) */
}



/*
 * Write "n" bytes to a descriptor.
 * Use in place of write() when fd is a stream socket
 *
 * We return the number of bytes written
 */

int
writen(fd, ptr, nbytes)
int	fd;
char	*ptr;
int	nbytes;
{
	int nleft, nwritten;

	nleft = nbytes;
	while(nleft > 0) {
		nwritten = write(fd, ptr, nleft);
		if (nwritten <= 0)
			return(nwritten);	/* error */

		nleft	-= nwritten;
		ptr	+= nwritten;
	}
	return(nbytes - nleft);
}


/*
 * Writestring uses the writen and strlen calls to write a
 * string to the file descriptor fd.  If the write fails
 * a -1 is returned. Otherwise zero is returned.
 */

int
writestring(fd, stringptr)
int	fd;
char	*stringptr;
{
	int length;

	length = strlen(stringptr);
	if (writen(fd, stringptr, length) != length)
		return(-1);
	else
		return(0);
}


/*
 * Read a line from a descriptor.  Read the line one byte at a time,
 * looking for the newline.  We store the newline in the buffer,
 * then follow it with a null (the same as fgets(3)).
 * We return the number of characters up to, but not including,
 * the null (the same as strlen(3))
 */

int
readline(fd, ptr, maxlen)
int	fd;
char	*ptr;
int 	maxlen;
{
	int n;
	int rc;
	char c;

	for (n=1; n < maxlen; n++) {
		if ( (rc = read(fd, &c, 1)) == 1) {
			*ptr++ = c;
			if (c == '\n')
				break;
		}
		else if (rc == 0) {
			if (n == 1)
				return(0);	/* EOF, no data read */
			else
				break;		/* EOF, some data was read */
		}
		else
			return(-1);		/* error */
	}

	*ptr = 0; 				/* Tack a NULL on the end */
	return(n);
}


/*
 * Read a stream socket one line at a time, and write each
 * line back to the sender
 *
 * Return when the connection is terminated
 */

#define MAXLINE 512

void
str_echo(sockfd)
int sockfd;
{
	int n;
	char line[MAXLINE];

	for ( ; ; ){
		n = readline(sockfd, line, MAXLINE);
		if (n == 0)
			return;
		else if (n < 0)
			err_dump("str_echo: readline error");

		if (writen(sockfd, line, n) != n)
			err_dump("str_echo: writen error");
	}
}



/*
 * Read the contents of the FILE *fp, write each line to the
 * stream socket (to the server process), then read a line back from
 * the socket and write it to the standard output.
 *
 * Return to the caller when an EOF is encountered on the input file.
 */

#include <stdio.h>
#define	 MAXLINE 512

void
str_cli(fp, sockfd)
FILE *fp;
int sockfd;
{
	int n;
	char sendline[MAXLINE];
	char recline[MAXLINE+1];

	while (fgets(sendline, MAXLINE, fp) != NULL) {
		n = strlen(sendline);
		if (writen(sockfd, sendline, n) != n)
			err_sys("str_cli: writen error on socket");
	
		/*
		 * Now read a line from the socket and write it to
		 * our standard output
		 */

		n = readline(sockfd, recline, MAXLINE);
		if (n<0)
			err_dump("str_cli: readline error");
		recline[n]=0;
		fputs(recline, stdout);
	}

	if (ferror(fp))
		err_sys("str_cli: error reading file");
}
